From 2d6f0d0cd94f9b8b24102300d8dd9cbbd1688826 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 4 May 2008 22:34:49 -0500 Subject: [SCSI] gdth: fix timer handling The global timer handling is problematic in that if someone unbinds a PCI gdth instance, the BUG_ON() in the timer will cause a panic. Fix this by making the timer start and stop depending on whether there are instances present. This should also permit binding and unbinding to work. Signed-off-by: James Bottomley --- drivers/scsi/gdth.c | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 8e2e964..16785a2 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -3724,6 +3724,8 @@ static void gdth_log_event(gdth_evt_data *dvr, char *buffer) } #ifdef GDTH_STATISTICS +static unchar gdth_timer_running; + static void gdth_timeout(ulong data) { ulong32 i; @@ -3731,7 +3733,10 @@ static void gdth_timeout(ulong data) gdth_ha_str *ha; ulong flags; - BUG_ON(list_empty(&gdth_instances)); + if(unlikely(list_empty(&gdth_instances))) { + gdth_timer_running = 0; + return; + } ha = list_first_entry(&gdth_instances, gdth_ha_str, list); spin_lock_irqsave(&ha->smp_lock, flags); @@ -3751,6 +3756,22 @@ static void gdth_timeout(ulong data) add_timer(&gdth_timer); spin_unlock_irqrestore(&ha->smp_lock, flags); } + +static void gdth_timer_init(void) +{ + if (gdth_timer_running) + return; + gdth_timer_running = 1; + TRACE2(("gdth_detect(): Initializing timer !\n")); + gdth_timer.expires = jiffies + HZ; + gdth_timer.data = 0L; + gdth_timer.function = gdth_timeout; + add_timer(&gdth_timer); +} +#else +static inline void gdth_timer_init(void) +{ +} #endif static void __init internal_setup(char *str,int *ints) @@ -4735,6 +4756,7 @@ static int __init gdth_isa_probe_one(ulong32 isa_bios) if (error) goto out_free_coal_stat; list_add_tail(&ha->list, &gdth_instances); + gdth_timer_init(); scsi_scan_host(shp); @@ -4865,6 +4887,7 @@ static int __init gdth_eisa_probe_one(ushort eisa_slot) if (error) goto out_free_coal_stat; list_add_tail(&ha->list, &gdth_instances); + gdth_timer_init(); scsi_scan_host(shp); @@ -5011,6 +5034,7 @@ static int gdth_pci_probe_one(gdth_pci_str *pcistr, list_add_tail(&ha->list, &gdth_instances); pci_set_drvdata(ha->pdev, ha); + gdth_timer_init(); scsi_scan_host(shp); @@ -5110,6 +5134,7 @@ static int __init gdth_init(void) /* initializations */ gdth_polling = TRUE; gdth_clear_events(); + init_timer(&gdth_timer); /* As default we do not probe for EISA or ISA controllers */ if (probe_eisa_isa) { @@ -5138,17 +5163,6 @@ static int __init gdth_init(void) TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count)); - if (list_empty(&gdth_instances)) - return -ENODEV; - -#ifdef GDTH_STATISTICS - TRACE2(("gdth_detect(): Initializing timer !\n")); - init_timer(&gdth_timer); - gdth_timer.expires = jiffies + HZ; - gdth_timer.data = 0L; - gdth_timer.function = gdth_timeout; - add_timer(&gdth_timer); -#endif major = register_chrdev(0,"gdth", &gdth_fops); register_reboot_notifier(&gdth_notifier); gdth_polling = FALSE; -- cgit v1.1 From a85591fd0baf4ed3f03ee1aaac6a985e400cf089 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sun, 4 May 2008 22:35:58 -0500 Subject: [SCSI] gdth: fix Error: Driver 'gdth' is already registered, aborting... This message appears on modprobe/rmmod/modprobe of the driver. It's caused because if the driver has no instances, it returns an error from gdth_init, which causes the module to fail to load. Unfortunately, the module's pci driver is still registered at this point. Fix this by making gdth behave like a modern driver and insert even if it doesn't find any instances (in case of hot plug or software driven binding). Signed-off-by: James Bottomley --- drivers/scsi/gdth.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 16785a2..46771d4 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -550,7 +550,6 @@ static int __init gdth_search_isa(ulong32 bios_adr) #endif /* CONFIG_ISA */ #ifdef CONFIG_PCI -static bool gdth_pci_registered; static bool gdth_search_vortex(ushort device) { @@ -5157,8 +5156,13 @@ static int __init gdth_init(void) #ifdef CONFIG_PCI /* scanning for PCI controllers */ - if (pci_register_driver(&gdth_pci_driver) == 0) - gdth_pci_registered = true; + if (pci_register_driver(&gdth_pci_driver)) { + gdth_ha_str *ha; + + list_for_each_entry(ha, &gdth_instances, list) + gdth_remove_one(ha); + return -ENODEV; + } #endif /* CONFIG_PCI */ TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count)); @@ -5181,8 +5185,7 @@ static void __exit gdth_exit(void) #endif #ifdef CONFIG_PCI - if (gdth_pci_registered) - pci_unregister_driver(&gdth_pci_driver); + pci_unregister_driver(&gdth_pci_driver); #endif list_for_each_entry(ha, &gdth_instances, list) -- cgit v1.1 From 4cf1043593db6a337f10e006c23c69e5fc93e722 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Wed, 7 May 2008 20:43:52 -0500 Subject: [SCSI] libiscsi regression in 2.6.25: fix nop timer handling The following patch fixes a bug in the iscsi nop processing. The target sends iscsi nops to ping the initiator and the initiator has to send nops to reply and can send nops to ping the target. In 2.6.25 we moved the nop processing to the kernel to handle problems when the userspace daemon is not up, but the target is pinging us, and to handle when scsi commands timeout, but the transport may be the cause (we can send a nop to check the transport). When we added this code we added a bug where if the transport timer wakes at the exact same time we are supposed to check for a nop timeout we drop the session instead of checking the transport. This patch checks if a iscsi ping is outstanding and if the ping has timed out, to determine if we need to signal a connection problem. Signed-off-by: Mike Christie Cc: Stable Tree Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 010c1b9..98164f3 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -1453,19 +1453,20 @@ static void iscsi_check_transport_timeouts(unsigned long data) { struct iscsi_conn *conn = (struct iscsi_conn *)data; struct iscsi_session *session = conn->session; - unsigned long timeout, next_timeout = 0, last_recv; + unsigned long recv_timeout, next_timeout = 0, last_recv; spin_lock(&session->lock); if (session->state != ISCSI_STATE_LOGGED_IN) goto done; - timeout = conn->recv_timeout; - if (!timeout) + recv_timeout = conn->recv_timeout; + if (!recv_timeout) goto done; - timeout *= HZ; + recv_timeout *= HZ; last_recv = conn->last_recv; - if (time_before_eq(last_recv + timeout + (conn->ping_timeout * HZ), + if (conn->ping_mtask && + time_before_eq(conn->last_ping + (conn->ping_timeout * HZ), jiffies)) { iscsi_conn_printk(KERN_ERR, conn, "ping timeout of %d secs " "expired, last rx %lu, last ping %lu, " @@ -1476,15 +1477,15 @@ static void iscsi_check_transport_timeouts(unsigned long data) return; } - if (time_before_eq(last_recv + timeout, jiffies)) { + if (time_before_eq(last_recv + recv_timeout, jiffies)) { if (time_before_eq(conn->last_ping, last_recv)) { /* send a ping to try to provoke some traffic */ debug_scsi("Sending nopout as ping on conn %p\n", conn); iscsi_send_nopout(conn, NULL); } - next_timeout = last_recv + timeout + (conn->ping_timeout * HZ); + next_timeout = conn->last_ping + (conn->ping_timeout * HZ); } else - next_timeout = last_recv + timeout; + next_timeout = last_recv + recv_timeout; debug_scsi("Setting next tmo %lu\n", next_timeout); mod_timer(&conn->transport_timer, next_timeout); -- cgit v1.1 From c8611f975403dd20e6503aff8aded5dcb718f75b Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Thu, 8 May 2008 20:15:34 -0500 Subject: [SCSI] libiscsi regression in 2.6.25: fix setting of recv timer If the ping tmo is longer than the recv tmo then we could miss a window where we were supposed to check the recv tmo. This happens because the ping code will set the next timeout for the ping timeout, and if the ping executes quickly there will be a long chunk of time before the timer wakes up again. This patch has the ping processing code kick off a recv tmo check when getting a nop in response to our ping. Signed-off-by: Mike Christie Cc: Stable Tree Signed-off-by: James Bottomley --- drivers/scsi/libiscsi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 98164f3..b43bf1d 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -730,7 +730,9 @@ static int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr, if (iscsi_recv_pdu(conn->cls_conn, hdr, data, datalen)) rc = ISCSI_ERR_CONN_FAILED; - } + } else + mod_timer(&conn->transport_timer, + jiffies + conn->recv_timeout); iscsi_free_mgmt_task(conn, mtask); break; default: @@ -1478,11 +1480,9 @@ static void iscsi_check_transport_timeouts(unsigned long data) } if (time_before_eq(last_recv + recv_timeout, jiffies)) { - if (time_before_eq(conn->last_ping, last_recv)) { - /* send a ping to try to provoke some traffic */ - debug_scsi("Sending nopout as ping on conn %p\n", conn); - iscsi_send_nopout(conn, NULL); - } + /* send a ping to try to provoke some traffic */ + debug_scsi("Sending nopout as ping on conn %p\n", conn); + iscsi_send_nopout(conn, NULL); next_timeout = conn->last_ping + (conn->ping_timeout * HZ); } else next_timeout = last_recv + recv_timeout; -- cgit v1.1 From ad2fa42d044b98469449880474a9662fb689f7f9 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 10 May 2008 08:33:58 -0500 Subject: [SCSI] aha152x: fix init suspiciously returned 1, it should follow 0/-E convention Reported-by: Frank de Jong > [1.] One line summary of the problem: > linux-2.6.25.3, aha152x'->init suspiciously returned 1, it should > follow 0/-E convention. The module / driver works okay. Unloading the > module is impossible. The driver is apparently returning 0 on failure and 1 on success. That's a bit unfortunate. Fix it by altering to -ENODEV and 0. Cc: Stable Tree Signed-off-by: James Bottomley --- drivers/scsi/aha152x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index f5215fd..f0c4ffc 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -3830,7 +3830,7 @@ static int __init aha152x_init(void) iounmap(p); } if (!ok && setup_count == 0) - return 0; + return -ENODEV; printk(KERN_INFO "aha152x: BIOS test: passed, "); #else @@ -3909,7 +3909,7 @@ static int __init aha152x_init(void) #endif } - return 1; + return 0; } static void __exit aha152x_exit(void) -- cgit v1.1 From 64976a0387835a7ac61bbe2a99b27ccae34eac5d Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 10 May 2008 14:08:40 -0500 Subject: [SCSI] aha152x: Fix oops on module removal Reported-by: Frank de Jong > after trying to unload the module: > BUG: unable to handle kernel paging request at 00100100 > IP: [] :aha152x:aha152x_exit+0x47/0x6a > *pde = 00000000 > Oops: 0000 [#1] PREEMPT SMP > Modules linked in: aha152x(-) w83781d hwmon_vid tun ne 8390 bonding > usb_storage snd_usb_audio snd_usb_lib snd_rawmidi pwc snd_seq_device > compat_ioctl32 snd_hwdep videodev v4l1_compat 3c59x mii intel_agp > agpgart snd_pcm_oss snd_pcm snd_timer snd_page_alloc snd_mixer_oss snd > > Pid: 2837, comm: rmmod Not tainted (2.6.25.3 #1) > EIP: 0060:[] EFLAGS: 00210212 CPU: 0 > EIP is at aha152x_exit+0x47/0x6a [aha152x] > EAX: 00000001 EBX: 000ffdc4 ECX: f7c517a8 EDX: 00000001 > ESI: 00000000 EDI: 00000003 EBP: e7880000 ESP: e7881f58 > DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 > Process rmmod (pid: 2837, ti=e7880000 task=f27eb580 task.ti=e7880000) > Stack: fba03700 c01419d2 31616861 00783235 e795ee70 c0157709 b7f24000 e79ae000 > c0158271 ffffffff b7f25000 e79ae004 e795e370 b7f25000 e795e37c e795e370 > 009ae000 fba03700 00000880 e7881fa8 00000000 bf93ec20 bf93ec20 c0102faa > Call Trace: > [] sys_delete_module+0x112/0x1a0 > [] remove_vma+0x39/0x50 > [] do_munmap+0x181/0x1f0 > [] sysenter_past_esp+0x5f/0x85 > [] rsc_parse+0x0/0x3c0 The problem is that the driver calls aha152x_release() under a list_for_each_entry(). Unfortunately, aha152x_release() deletes from the list in question. Fix this by using list_for_each_entry_safe(). Cc: Stable Tree Signed-off-by: James Bottomley --- drivers/scsi/aha152x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index f0c4ffc..1dca177 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -3914,9 +3914,9 @@ static int __init aha152x_init(void) static void __exit aha152x_exit(void) { - struct aha152x_hostdata *hd; + struct aha152x_hostdata *hd, *tmp; - list_for_each_entry(hd, &aha152x_host_list, host_list) { + list_for_each_entry_safe(hd, tmp, &aha152x_host_list, host_list) { struct Scsi_Host *shost = container_of((void *)hd, struct Scsi_Host, hostdata); aha152x_release(shost); -- cgit v1.1 From f9af857489cc19ee3acd0d5248dca7d243e353a5 Mon Sep 17 00:00:00 2001 From: Matheos Worku Date: Mon, 12 May 2008 03:10:59 -0700 Subject: niu: Determine the # of ports from the card's VPD data Determine the number of physical ports from the card's VPD data. Previous fix failed on Maramba platform which doesn't have the "board-model" property. This fix uses the "model" property which exists on all cards and Neptune based motherboards. cstyle cleanup included. Signed-off-by: Matheos Worku Signed-off-by: David S. Miller --- drivers/net/niu.c | 53 +++++++++++++++++++++-------------------------------- drivers/net/niu.h | 9 +++++++++ 2 files changed, 30 insertions(+), 32 deletions(-) diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 57cfd72..918f802 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c @@ -865,7 +865,6 @@ static int link_status_1g_serdes(struct niu *np, int *link_up_p) return 0; } - static int link_status_10g_serdes(struct niu *np, int *link_up_p) { unsigned long flags; @@ -900,7 +899,6 @@ static int link_status_10g_serdes(struct niu *np, int *link_up_p) return 0; } - static int link_status_1g_rgmii(struct niu *np, int *link_up_p) { struct niu_link_config *lp = &np->link_config; @@ -957,7 +955,6 @@ out: return err; } - static int bcm8704_reset(struct niu *np) { int err, limit; @@ -1357,8 +1354,6 @@ static int mii_reset(struct niu *np) return 0; } - - static int xcvr_init_1g_rgmii(struct niu *np) { int err; @@ -1419,7 +1414,6 @@ static int xcvr_init_1g_rgmii(struct niu *np) return 0; } - static int mii_init_common(struct niu *np) { struct niu_link_config *lp = &np->link_config; @@ -7008,31 +7002,20 @@ static int __devinit niu_phy_type_prop_decode(struct niu *np, return 0; } -/* niu board models have a trailing dash version incremented - * with HW rev change. Need to ingnore the dash version while - * checking for match - * - * for example, for the 10G card the current vpd.board_model - * is 501-5283-04, of which -04 is the dash version and have - * to be ignored - */ -static int niu_board_model_match(struct niu *np, const char *model) -{ - return !strncmp(np->vpd.board_model, model, strlen(model)); -} - static int niu_pci_vpd_get_nports(struct niu *np) { int ports = 0; - if ((niu_board_model_match(np, NIU_QGC_LP_BM_STR)) || - (niu_board_model_match(np, NIU_QGC_PEM_BM_STR)) || - (niu_board_model_match(np, NIU_ALONSO_BM_STR))) { + if ((!strcmp(np->vpd.model, NIU_QGC_LP_MDL_STR)) || + (!strcmp(np->vpd.model, NIU_QGC_PEM_MDL_STR)) || + (!strcmp(np->vpd.model, NIU_MARAMBA_MDL_STR)) || + (!strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) || + (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR))) { ports = 4; - } else if ((niu_board_model_match(np, NIU_2XGF_LP_BM_STR)) || - (niu_board_model_match(np, NIU_2XGF_PEM_BM_STR)) || - (niu_board_model_match(np, NIU_FOXXY_BM_STR)) || - (niu_board_model_match(np, NIU_2XGF_MRVL_BM_STR))) { + } else if ((!strcmp(np->vpd.model, NIU_2XGF_LP_MDL_STR)) || + (!strcmp(np->vpd.model, NIU_2XGF_PEM_MDL_STR)) || + (!strcmp(np->vpd.model, NIU_FOXXY_MDL_STR)) || + (!strcmp(np->vpd.model, NIU_2XGF_MRVL_MDL_STR))) { ports = 2; } @@ -7053,8 +7036,8 @@ static void __devinit niu_pci_vpd_validate(struct niu *np) return; } - if (!strcmp(np->vpd.model, "SUNW,CP3220") || - !strcmp(np->vpd.model, "SUNW,CP3260")) { + if (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR) || + !strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) { np->flags |= NIU_FLAGS_10G; np->flags &= ~NIU_FLAGS_FIBER; np->flags |= NIU_FLAGS_XCVR_SERDES; @@ -7065,7 +7048,7 @@ static void __devinit niu_pci_vpd_validate(struct niu *np) } if (np->flags & NIU_FLAGS_10G) np->mac_xcvr = MAC_XCVR_XPCS; - } else if (niu_board_model_match(np, NIU_FOXXY_BM_STR)) { + } else if (!strcmp(np->vpd.model, NIU_FOXXY_MDL_STR)) { np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER | NIU_FLAGS_HOTPLUG_PHY); } else if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) { @@ -7541,8 +7524,8 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent) u32 val; int err; - if (!strcmp(np->vpd.model, "SUNW,CP3220") || - !strcmp(np->vpd.model, "SUNW,CP3260")) { + if (!strcmp(np->vpd.model, NIU_ALONSO_MDL_STR) || + !strcmp(np->vpd.model, NIU_KIMI_MDL_STR)) { num_10g = 0; num_1g = 2; parent->plat_type = PLAT_TYPE_ATCA_CP3220; @@ -7551,7 +7534,7 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent) phy_encode(PORT_TYPE_1G, 1) | phy_encode(PORT_TYPE_1G, 2) | phy_encode(PORT_TYPE_1G, 3)); - } else if (niu_board_model_match(np, NIU_FOXXY_BM_STR)) { + } else if (!strcmp(np->vpd.model, NIU_FOXXY_MDL_STR)) { num_10g = 2; num_1g = 0; parent->num_ports = 2; @@ -7946,6 +7929,7 @@ static int __devinit niu_get_of_props(struct niu *np) struct device_node *dp; const char *phy_type; const u8 *mac_addr; + const char *model; int prop_len; if (np->parent->plat_type == PLAT_TYPE_NIU) @@ -8000,6 +7984,11 @@ static int __devinit niu_get_of_props(struct niu *np) memcpy(dev->dev_addr, dev->perm_addr, dev->addr_len); + model = of_get_property(dp, "model", &prop_len); + + if (model) + strcpy(np->vpd.model, model); + return 0; #else return -EINVAL; diff --git a/drivers/net/niu.h b/drivers/net/niu.h index 97ffbe1..12fd570 100644 --- a/drivers/net/niu.h +++ b/drivers/net/niu.h @@ -2946,6 +2946,15 @@ struct rx_ring_info { #define NIU_ALONSO_BM_STR "373-0202" #define NIU_FOXXY_BM_STR "501-7961" #define NIU_2XGF_MRVL_BM_STR "SK-6E82" +#define NIU_QGC_LP_MDL_STR "SUNW,pcie-qgc" +#define NIU_2XGF_LP_MDL_STR "SUNW,pcie-2xgf" +#define NIU_QGC_PEM_MDL_STR "SUNW,pcie-qgc-pem" +#define NIU_2XGF_PEM_MDL_STR "SUNW,pcie-2xgf-pem" +#define NIU_ALONSO_MDL_STR "SUNW,CP3220" +#define NIU_KIMI_MDL_STR "SUNW,CP3260" +#define NIU_MARAMBA_MDL_STR "SUNW,pcie-neptune" +#define NIU_FOXXY_MDL_STR "SUNW,pcie-rfem" +#define NIU_2XGF_MRVL_MDL_STR "SysKonnect,pcie-2xgf" #define NIU_VPD_MIN_MAJOR 3 #define NIU_VPD_MIN_MINOR 4 -- cgit v1.1 From 6e40a915de82e00d18f75941e531b40c4e0d94c4 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 9 May 2008 15:11:17 -0700 Subject: sctp: Do not enable peer IPv6 address support on PF_INET socket If socket is create by PF_INET type, it can not used IPv6 address to send/recv DATA, So we can not used IPv6 address even if peer tell us it support IPv6 address. This patch fix to only enabled peer IPv6 address support on PF_INET6 socket. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/sm_make_chunk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 81b6064..69a464f 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2418,7 +2418,8 @@ static int sctp_process_param(struct sctp_association *asoc, break; case SCTP_PARAM_IPV6_ADDRESS: - asoc->peer.ipv6_address = 1; + if (PF_INET6 == asoc->base.sk->sk_family) + asoc->peer.ipv6_address = 1; break; case SCTP_PARAM_HOST_NAME_ADDRESS: -- cgit v1.1 From c4492586a618d18e8a5343a04bad0ec606064846 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 9 May 2008 15:11:53 -0700 Subject: sctp: Add address type check while process paramaters of ASCONF chunk If socket is create by AF_INET type, add IPv6 address to asoc will cause kernel panic while packet is transmitted on that transport. This patch add address type check before process paramaters of ASCONF chunk. If peer is not support this address type, return with error invald parameter. Signed-off-by: Wei Yongjun Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/sm_make_chunk.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 69a464f..6eeee53 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2827,6 +2827,19 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, union sctp_addr addr; union sctp_addr_param *addr_param; + switch (addr_param->v4.param_hdr.type) { + case SCTP_PARAM_IPV6_ADDRESS: + if (!asoc->peer.ipv6_address) + return SCTP_ERROR_INV_PARAM; + break; + case SCTP_PARAM_IPV4_ADDRESS: + if (!asoc->peer.ipv4_address) + return SCTP_ERROR_INV_PARAM; + break; + default: + return SCTP_ERROR_INV_PARAM; + } + addr_param = (union sctp_addr_param *) ((void *)asconf_param + sizeof(sctp_addip_param_t)); -- cgit v1.1 From 4951704b4e23d71b99ac933d8e6993bc6225ac13 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 12 May 2008 03:29:11 -0700 Subject: syncppp: Fix crashes. The syncppp layer wants a mid-level netdev private pointer. It was using netdev->priv but that only worked by accident, and thus this scheme was broken when the device private allocation strategy changed. Add a proper mid-layer private pointer for uses like this, update syncppp and all users, and remove the HDLC_PPP broken tag from drivers/net/wan/Kconfig Signed-off-by: David S. Miller --- drivers/net/wan/Kconfig | 4 +--- drivers/net/wan/cosa.c | 14 +++++++------- drivers/net/wan/hdlc_ppp.c | 2 +- drivers/net/wan/hostess_sv11.c | 12 ++++++------ drivers/net/wan/lmc/lmc_main.c | 1 + drivers/net/wan/sealevel.c | 1 + include/linux/netdevice.h | 3 +++ include/net/syncppp.h | 2 +- 8 files changed, 21 insertions(+), 18 deletions(-) diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 8005dd1..d5140ae 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -150,11 +150,9 @@ config HDLC_FR config HDLC_PPP tristate "Synchronous Point-to-Point Protocol (PPP) support" - depends on HDLC && BROKEN + depends on HDLC help Generic HDLC driver supporting PPP over WAN connections. - This module is currently broken and will cause a kernel panic - when a device configured in PPP mode is activated. It will be replaced by new PPP implementation in Linux 2.6.26. diff --git a/drivers/net/wan/cosa.c b/drivers/net/wan/cosa.c index 45ddfc9..b0fce13 100644 --- a/drivers/net/wan/cosa.c +++ b/drivers/net/wan/cosa.c @@ -629,7 +629,7 @@ static void sppp_channel_init(struct channel_data *chan) d->base_addr = chan->cosa->datareg; d->irq = chan->cosa->irq; d->dma = chan->cosa->dma; - d->priv = chan; + d->ml_priv = chan; sppp_attach(&chan->pppdev); if (register_netdev(d)) { printk(KERN_WARNING "%s: register_netdev failed.\n", d->name); @@ -650,7 +650,7 @@ static void sppp_channel_delete(struct channel_data *chan) static int cosa_sppp_open(struct net_device *d) { - struct channel_data *chan = d->priv; + struct channel_data *chan = d->ml_priv; int err; unsigned long flags; @@ -690,7 +690,7 @@ static int cosa_sppp_open(struct net_device *d) static int cosa_sppp_tx(struct sk_buff *skb, struct net_device *dev) { - struct channel_data *chan = dev->priv; + struct channel_data *chan = dev->ml_priv; netif_stop_queue(dev); @@ -701,7 +701,7 @@ static int cosa_sppp_tx(struct sk_buff *skb, struct net_device *dev) static void cosa_sppp_timeout(struct net_device *dev) { - struct channel_data *chan = dev->priv; + struct channel_data *chan = dev->ml_priv; if (test_bit(RXBIT, &chan->cosa->rxtx)) { chan->stats.rx_errors++; @@ -720,7 +720,7 @@ static void cosa_sppp_timeout(struct net_device *dev) static int cosa_sppp_close(struct net_device *d) { - struct channel_data *chan = d->priv; + struct channel_data *chan = d->ml_priv; unsigned long flags; netif_stop_queue(d); @@ -800,7 +800,7 @@ static int sppp_tx_done(struct channel_data *chan, int size) static struct net_device_stats *cosa_net_stats(struct net_device *dev) { - struct channel_data *chan = dev->priv; + struct channel_data *chan = dev->ml_priv; return &chan->stats; } @@ -1217,7 +1217,7 @@ static int cosa_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { int rv; - struct channel_data *chan = dev->priv; + struct channel_data *chan = dev->ml_priv; rv = cosa_ioctl_common(chan->cosa, chan, cmd, (unsigned long)ifr->ifr_data); if (rv == -ENOIOCTLCMD) { return sppp_do_ioctl(dev, ifr, cmd); diff --git a/drivers/net/wan/hdlc_ppp.c b/drivers/net/wan/hdlc_ppp.c index 10396d9..0030833 100644 --- a/drivers/net/wan/hdlc_ppp.c +++ b/drivers/net/wan/hdlc_ppp.c @@ -45,7 +45,7 @@ static int ppp_open(struct net_device *dev) int (*old_ioctl)(struct net_device *, struct ifreq *, int); int result; - dev->priv = &state(hdlc)->syncppp_ptr; + dev->ml_priv = &state(hdlc)->syncppp_ptr; state(hdlc)->syncppp_ptr = &state(hdlc)->pppdev; state(hdlc)->pppdev.dev = dev; diff --git a/drivers/net/wan/hostess_sv11.c b/drivers/net/wan/hostess_sv11.c index 83dbc92..f3065d3 100644 --- a/drivers/net/wan/hostess_sv11.c +++ b/drivers/net/wan/hostess_sv11.c @@ -75,7 +75,7 @@ static void hostess_input(struct z8530_channel *c, struct sk_buff *skb) static int hostess_open(struct net_device *d) { - struct sv11_device *sv11=d->priv; + struct sv11_device *sv11=d->ml_priv; int err = -1; /* @@ -128,7 +128,7 @@ static int hostess_open(struct net_device *d) static int hostess_close(struct net_device *d) { - struct sv11_device *sv11=d->priv; + struct sv11_device *sv11=d->ml_priv; /* * Discard new frames */ @@ -159,14 +159,14 @@ static int hostess_close(struct net_device *d) static int hostess_ioctl(struct net_device *d, struct ifreq *ifr, int cmd) { - /* struct sv11_device *sv11=d->priv; + /* struct sv11_device *sv11=d->ml_priv; z8530_ioctl(d,&sv11->sync.chanA,ifr,cmd) */ return sppp_do_ioctl(d, ifr,cmd); } static struct net_device_stats *hostess_get_stats(struct net_device *d) { - struct sv11_device *sv11=d->priv; + struct sv11_device *sv11=d->ml_priv; if(sv11) return z8530_get_stats(&sv11->sync.chanA); else @@ -179,7 +179,7 @@ static struct net_device_stats *hostess_get_stats(struct net_device *d) static int hostess_queue_xmit(struct sk_buff *skb, struct net_device *d) { - struct sv11_device *sv11=d->priv; + struct sv11_device *sv11=d->ml_priv; return z8530_queue_xmit(&sv11->sync.chanA, skb); } @@ -325,6 +325,7 @@ static struct sv11_device *sv11_init(int iobase, int irq) /* * Initialise the PPP components */ + d->ml_priv = sv; sppp_attach(&sv->netdev); /* @@ -333,7 +334,6 @@ static struct sv11_device *sv11_init(int iobase, int irq) d->base_addr = iobase; d->irq = irq; - d->priv = sv; if(register_netdev(d)) { diff --git a/drivers/net/wan/lmc/lmc_main.c b/drivers/net/wan/lmc/lmc_main.c index 6635ece..62133ce 100644 --- a/drivers/net/wan/lmc/lmc_main.c +++ b/drivers/net/wan/lmc/lmc_main.c @@ -891,6 +891,7 @@ static int __devinit lmc_init_one(struct pci_dev *pdev, /* Initialize the sppp layer */ /* An ioctl can cause a subsequent detach for raw frame interface */ + dev->ml_priv = sc; sc->if_type = LMC_PPP; sc->check = 0xBEAFCAFE; dev->base_addr = pci_resource_start(pdev, 0); diff --git a/drivers/net/wan/sealevel.c b/drivers/net/wan/sealevel.c index 11276bf..44a89df 100644 --- a/drivers/net/wan/sealevel.c +++ b/drivers/net/wan/sealevel.c @@ -241,6 +241,7 @@ static inline struct slvl_device *slvl_alloc(int iobase, int irq) return NULL; sv = d->priv; + d->ml_priv = sv; sv->if_ptr = &sv->pppdev; sv->pppdev.dev = d; d->base_addr = iobase; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7c1d446..7469017 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -715,6 +715,9 @@ struct net_device struct net *nd_net; #endif + /* mid-layer private */ + void *ml_priv; + /* bridge stuff */ struct net_bridge_port *br_port; /* macvlan */ diff --git a/include/net/syncppp.h b/include/net/syncppp.h index 877efa4..e43f407 100644 --- a/include/net/syncppp.h +++ b/include/net/syncppp.h @@ -59,7 +59,7 @@ struct ppp_device static inline struct sppp *sppp_of(struct net_device *dev) { - struct ppp_device **ppp = dev->priv; + struct ppp_device **ppp = dev->ml_priv; BUG_ON((*ppp)->dev != dev); return &(*ppp)->sppp; } -- cgit v1.1 From 8965eb19386fdf5ccd0ef8b02593eb8560aa3416 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 May 2008 15:43:30 +0200 Subject: x86/pci: fix broken ISA DMA Rene Herman reported: > commit 8779f2fc3b84ebb6c5181fb13d702e9944c16069 > > "x86: don't try to allocate from DMA zone at first" > > breaks all of ISA DMA. Or all of ALSA ISA DMA at least. All > ISA soundcards are silent following that commit -- no error > messages, everything appears fine, just silence. That patch is buggy. We had an implicit assumption that dev = NULL for ISA devices that require 24bit DMA. The recent work on x86 dma_alloc_coherent() breaks the ISA DMA buffer allocation, which is represented by "dev = NULL" and requires 24bit DMA implicitly. Bisected-by: Rene Herman Signed-off-by: Takashi Iwai Tested-by: Rene Herman Signed-off-by: Ingo Molnar --- arch/x86/kernel/pci-dma.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 0c37f16..c5ef1af 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -385,11 +385,13 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, if (dma_alloc_from_coherent_mem(dev, size, dma_handle, &memory)) return memory; - if (!dev) + if (!dev) { dev = &fallback_dev; + gfp |= GFP_DMA; + } dma_mask = dev->coherent_dma_mask; if (dma_mask == 0) - dma_mask = DMA_32BIT_MASK; + dma_mask = (gfp & GFP_DMA) ? DMA_24BIT_MASK : DMA_32BIT_MASK; /* Device not DMA able */ if (dev->dma_mask == NULL) @@ -403,7 +405,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, larger than 16MB and in this case we have a chance of finding fitting memory in the next higher zone first. If not retry with true GFP_DMA. -AK */ - if (dma_mask <= DMA_32BIT_MASK) + if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA)) gfp |= GFP_DMA32; #endif -- cgit v1.1 From f8955ebe3ea85a9d3ff2685ee64386fd34434cf3 Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Sat, 10 May 2008 09:01:48 -0500 Subject: x86: [VOYAGER] fix duplicate phys_cpu_present_map symbol The phys_cpu_present_map is an expected symbol in the SMP harness. Unfortunately, x86 recently moved this and a few others to kernel/setup.c where it doesn't quite work because voyager has to define its own. Use CONFIG_X86_LOCAL_APIC to isolate these definitions and fix up another area in setup.c where CONFIG_X86_SMP should be used instead of CONFIG_SMP. Signed-off-by: James Bottomley Cc: WANG Cong Cc: toralf.foerster@gmx.de Cc: Mike Travis Cc: Alexey Starikovskiy Signed-off-by: Thomas Gleixner --- arch/x86/kernel/setup.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index c0c68c1..6f80b85 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -12,6 +12,7 @@ #include #include +#ifdef CONFIG_X86_LOCAL_APIC unsigned int num_processors; unsigned disabled_cpus __cpuinitdata; /* Processor that is doing the boot up */ @@ -23,8 +24,9 @@ EXPORT_PER_CPU_SYMBOL(x86_cpu_to_apicid); /* Bitmask of physically existing CPUs */ physid_mask_t phys_cpu_present_map; +#endif -#if defined(CONFIG_HAVE_SETUP_PER_CPU_AREA) && defined(CONFIG_SMP) +#if defined(CONFIG_HAVE_SETUP_PER_CPU_AREA) && defined(CONFIG_X86_SMP) /* * Copy data used in early init routines from the initial arrays to the * per cpu data areas. These arrays then become expendable and the -- cgit v1.1 From 8c6b0ef2ea1bb42cd72d987389297f66cd25790b Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Sun, 11 May 2008 22:46:38 +0400 Subject: x86: wakeup.lds.S - section ordering fix To allow linker to catch sections overlapping we have to declare them in appropriate order. Signed-off-by: Cyrill Gorcunov Cc: Sam Ravnborg Acked-by: Pavel Machek Signed-off-by: Thomas Gleixner --- arch/x86/kernel/acpi/realmode/wakeup.lds.S | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/kernel/acpi/realmode/wakeup.lds.S b/arch/x86/kernel/acpi/realmode/wakeup.lds.S index 22fab6c..7da00b7 100644 --- a/arch/x86/kernel/acpi/realmode/wakeup.lds.S +++ b/arch/x86/kernel/acpi/realmode/wakeup.lds.S @@ -12,11 +12,6 @@ ENTRY(_start) SECTIONS { - . = HEADER_OFFSET; - .header : { - *(.header) - } - . = 0; .text : { *(.text*) @@ -50,6 +45,11 @@ SECTIONS __bss_end = .; } + . = HEADER_OFFSET; + .header : { + *(.header) + } + . = ALIGN(16); _end = .; -- cgit v1.1 From 5dc474d6b3ba19df7d491d4eabd9fb7a0c1c2423 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 12 May 2008 15:43:46 -0700 Subject: pppol2tp: Remove null pointer dereference. If session is NULL, it is not possible to access its name field. So I have split apart the printing of the error message to drop the printing of the name field in this case. The macro PRINTK actually only evaluates its arguments starting with the third one if the bitwise conjunction of the first two is non-zero. Normally, this conjunction would only be non-zero if debugging mode were turned on, but when session is NULL, the first argument in both the old and new code is -1, and thus the bitwise conjunction is true. Perhaps a different strategy is desired, such as using tunnel->debug, which session->debug is initialized to, but tunnel can also be NULL, so this does not completely solve the problem. This problem was found using the following semantic match (http://www.emn.fr/x-info/coccinelle/) // @@ expression E, E1; identifier f; statement S1,S2,S3; @@ * if (E == NULL) { ... when != if (E == NULL) S1 else S2 when != E = E1 * E->f ... when any return ...; } else S3 // Signed-off-by: Julia Lawall Signed-off-by: David S. Miller --- drivers/net/pppol2tp.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index 244d783..79359919 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -1621,9 +1621,16 @@ out_no_ppp: end: release_sock(sk); - if (error != 0) - PRINTK(session ? session->debug : -1, PPPOL2TP_MSG_CONTROL, KERN_WARNING, - "%s: connect failed: %d\n", session->name, error); + if (error != 0) { + if (session) + PRINTK(session->debug, + PPPOL2TP_MSG_CONTROL, KERN_WARNING, + "%s: connect failed: %d\n", + session->name, error); + else + PRINTK(-1, PPPOL2TP_MSG_CONTROL, KERN_WARNING, + "connect failed: %d\n", error); + } return error; } -- cgit v1.1 From 94d149c34cda933ff5096aca94bb23bf68602f4e Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 12 May 2008 16:33:33 -0700 Subject: sparc: Fix mremap address range validation. Just like mmap, we need to validate address ranges regardless of MAP_FIXED. sparc{,64}_mmap_check()'s flag argument is unused, remove. Based upon a report and preliminary patch by Jan Lieskovsky Signed-off-by: David S. Miller --- arch/sparc/kernel/sys_sparc.c | 48 ++++----------------------------------- arch/sparc64/kernel/sys_sparc.c | 36 ++++------------------------- arch/sparc64/kernel/sys_sparc32.c | 33 ++------------------------- include/asm-sparc/mman.h | 5 ++-- include/asm-sparc64/mman.h | 5 ++-- 5 files changed, 15 insertions(+), 112 deletions(-) diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c index e995491..3c6b49a 100644 --- a/arch/sparc/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc.c @@ -219,7 +219,7 @@ out: return err; } -int sparc_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) +int sparc_mmap_check(unsigned long addr, unsigned long len) { if (ARCH_SUN4C_SUN4 && (len > 0x20000000 || @@ -295,52 +295,14 @@ asmlinkage unsigned long sparc_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr) { - struct vm_area_struct *vma; unsigned long ret = -EINVAL; - if (ARCH_SUN4C_SUN4) { - if (old_len > 0x20000000 || new_len > 0x20000000) - goto out; - if (addr < 0xe0000000 && addr + old_len > 0x20000000) - goto out; - } - if (old_len > TASK_SIZE - PAGE_SIZE || - new_len > TASK_SIZE - PAGE_SIZE) + + if (unlikely(sparc_mmap_check(addr, old_len))) + goto out; + if (unlikely(sparc_mmap_check(new_addr, new_len))) goto out; down_write(¤t->mm->mmap_sem); - if (flags & MREMAP_FIXED) { - if (ARCH_SUN4C_SUN4 && - new_addr < 0xe0000000 && - new_addr + new_len > 0x20000000) - goto out_sem; - if (new_addr + new_len > TASK_SIZE - PAGE_SIZE) - goto out_sem; - } else if ((ARCH_SUN4C_SUN4 && addr < 0xe0000000 && - addr + new_len > 0x20000000) || - addr + new_len > TASK_SIZE - PAGE_SIZE) { - unsigned long map_flags = 0; - struct file *file = NULL; - - ret = -ENOMEM; - if (!(flags & MREMAP_MAYMOVE)) - goto out_sem; - - vma = find_vma(current->mm, addr); - if (vma) { - if (vma->vm_flags & VM_SHARED) - map_flags |= MAP_SHARED; - file = vma->vm_file; - } - - new_addr = get_unmapped_area(file, addr, new_len, - vma ? vma->vm_pgoff : 0, - map_flags); - ret = new_addr; - if (new_addr & ~PAGE_MASK) - goto out_sem; - flags |= MREMAP_FIXED; - } ret = do_mremap(addr, old_len, new_len, flags, new_addr); -out_sem: up_write(¤t->mm->mmap_sem); out: return ret; diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c index 0dbc941..ac1bff5 100644 --- a/arch/sparc64/kernel/sys_sparc.c +++ b/arch/sparc64/kernel/sys_sparc.c @@ -542,8 +542,7 @@ asmlinkage long sparc64_personality(unsigned long personality) return ret; } -int sparc64_mmap_check(unsigned long addr, unsigned long len, - unsigned long flags) +int sparc64_mmap_check(unsigned long addr, unsigned long len) { if (test_thread_flag(TIF_32BIT)) { if (len >= STACK_TOP32) @@ -609,46 +608,19 @@ asmlinkage unsigned long sys64_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, unsigned long new_addr) { - struct vm_area_struct *vma; unsigned long ret = -EINVAL; if (test_thread_flag(TIF_32BIT)) goto out; if (unlikely(new_len >= VA_EXCLUDE_START)) goto out; - if (unlikely(invalid_64bit_range(addr, old_len))) + if (unlikely(sparc64_mmap_check(addr, old_len))) + goto out; + if (unlikely(sparc64_mmap_check(new_addr, new_len))) goto out; down_write(¤t->mm->mmap_sem); - if (flags & MREMAP_FIXED) { - if (invalid_64bit_range(new_addr, new_len)) - goto out_sem; - } else if (invalid_64bit_range(addr, new_len)) { - unsigned long map_flags = 0; - struct file *file = NULL; - - ret = -ENOMEM; - if (!(flags & MREMAP_MAYMOVE)) - goto out_sem; - - vma = find_vma(current->mm, addr); - if (vma) { - if (vma->vm_flags & VM_SHARED) - map_flags |= MAP_SHARED; - file = vma->vm_file; - } - - /* MREMAP_FIXED checked above. */ - new_addr = get_unmapped_area(file, addr, new_len, - vma ? vma->vm_pgoff : 0, - map_flags); - ret = new_addr; - if (new_addr & ~PAGE_MASK) - goto out_sem; - flags |= MREMAP_FIXED; - } ret = do_mremap(addr, old_len, new_len, flags, new_addr); -out_sem: up_write(¤t->mm->mmap_sem); out: return ret; diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 1aa4288..ba5bd62 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c @@ -867,44 +867,15 @@ asmlinkage unsigned long sys32_mremap(unsigned long addr, unsigned long old_len, unsigned long new_len, unsigned long flags, u32 __new_addr) { - struct vm_area_struct *vma; unsigned long ret = -EINVAL; unsigned long new_addr = __new_addr; - if (old_len > STACK_TOP32 || new_len > STACK_TOP32) + if (unlikely(sparc64_mmap_check(addr, old_len))) goto out; - if (addr > STACK_TOP32 - old_len) + if (unlikely(sparc64_mmap_check(new_addr, new_len))) goto out; down_write(¤t->mm->mmap_sem); - if (flags & MREMAP_FIXED) { - if (new_addr > STACK_TOP32 - new_len) - goto out_sem; - } else if (addr > STACK_TOP32 - new_len) { - unsigned long map_flags = 0; - struct file *file = NULL; - - ret = -ENOMEM; - if (!(flags & MREMAP_MAYMOVE)) - goto out_sem; - - vma = find_vma(current->mm, addr); - if (vma) { - if (vma->vm_flags & VM_SHARED) - map_flags |= MAP_SHARED; - file = vma->vm_file; - } - - /* MREMAP_FIXED checked above. */ - new_addr = get_unmapped_area(file, addr, new_len, - vma ? vma->vm_pgoff : 0, - map_flags); - ret = new_addr; - if (new_addr & ~PAGE_MASK) - goto out_sem; - flags |= MREMAP_FIXED; - } ret = do_mremap(addr, old_len, new_len, flags, new_addr); -out_sem: up_write(¤t->mm->mmap_sem); out: return ret; diff --git a/include/asm-sparc/mman.h b/include/asm-sparc/mman.h index e18be98..3d16b40 100644 --- a/include/asm-sparc/mman.h +++ b/include/asm-sparc/mman.h @@ -24,9 +24,8 @@ #ifdef __KERNEL__ #ifndef __ASSEMBLY__ -#define arch_mmap_check sparc_mmap_check -int sparc_mmap_check(unsigned long addr, unsigned long len, - unsigned long flags); +#define arch_mmap_check(addr,len,flags) sparc_mmap_check(addr,len) +int sparc_mmap_check(unsigned long addr, unsigned long len); #endif #endif diff --git a/include/asm-sparc64/mman.h b/include/asm-sparc64/mman.h index e584563..625be4d 100644 --- a/include/asm-sparc64/mman.h +++ b/include/asm-sparc64/mman.h @@ -24,9 +24,8 @@ #ifdef __KERNEL__ #ifndef __ASSEMBLY__ -#define arch_mmap_check sparc64_mmap_check -int sparc64_mmap_check(unsigned long addr, unsigned long len, - unsigned long flags); +#define arch_mmap_check(addr,len,flags) sparc64_mmap_check(addr,len) +int sparc64_mmap_check(unsigned long addr, unsigned long len); #endif #endif -- cgit v1.1 From 4978db5bd964d90265f957f980ab2b0771ca2b9f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 12 May 2008 16:51:15 -0700 Subject: lmb: Fix inconsistent alignment of size argument. When allocating, if we will align up the size when making the reservation, we should also align the size for the check that the space is actually available. The simplest thing is to just aling the size up from the beginning, then we can use plain 'size' throughout. Signed-off-by: David S. Miller --- lib/lmb.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/lmb.c b/lib/lmb.c index 83287d3..93445dc 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -286,8 +286,7 @@ static u64 __init lmb_alloc_nid_unreserved(u64 start, u64 end, j = lmb_overlaps_region(&lmb.reserved, base, size); if (j < 0) { /* this area isn't reserved, take it */ - if (lmb_add_region(&lmb.reserved, base, - lmb_align_up(size, align)) < 0) + if (lmb_add_region(&lmb.reserved, base, size) < 0) base = ~(u64)0; return base; } @@ -333,6 +332,10 @@ u64 __init lmb_alloc_nid(u64 size, u64 align, int nid, struct lmb_region *mem = &lmb.memory; int i; + BUG_ON(0 == size); + + size = lmb_align_up(size, align); + for (i = 0; i < mem->cnt; i++) { u64 ret = lmb_alloc_nid_region(&mem->region[i], nid_range, @@ -370,6 +373,8 @@ u64 __init __lmb_alloc_base(u64 size, u64 align, u64 max_addr) BUG_ON(0 == size); + size = lmb_align_up(size, align); + /* On some platforms, make sure we allocate lowmem */ /* Note that LMB_REAL_LIMIT may be LMB_ALLOC_ANYWHERE */ if (max_addr == LMB_ALLOC_ANYWHERE) @@ -393,8 +398,7 @@ u64 __init __lmb_alloc_base(u64 size, u64 align, u64 max_addr) j = lmb_overlaps_region(&lmb.reserved, base, size); if (j < 0) { /* this area isn't reserved, take it */ - if (lmb_add_region(&lmb.reserved, base, - lmb_align_up(size, align)) < 0) + if (lmb_add_region(&lmb.reserved, base, size) < 0) return 0; return base; } -- cgit v1.1 From faa6cfde747ba6d37a0889cbe85881c80806d355 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 12 May 2008 17:21:55 -0700 Subject: lmb: Make lmb debugging more useful. Having to muck with the build and set DEBUG just to get lmb_dump_all() to print things isn't very useful. So use pr_info() and use an early boot param "lmb=debug" so we can simply ask users to reboot with this option when we need some debugging from them. Signed-off-by: David S. Miller --- lib/lmb.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/lmb.c b/lib/lmb.c index 93445dc..867f7b5 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -19,31 +19,42 @@ struct lmb lmb; +static int lmb_debug; + +static int __init early_lmb(char *p) +{ + if (p && strstr(p, "debug")) + lmb_debug = 1; + return 0; +} +early_param("lmb", early_lmb); + void lmb_dump_all(void) { -#ifdef DEBUG unsigned long i; - pr_debug("lmb_dump_all:\n"); - pr_debug(" memory.cnt = 0x%lx\n", lmb.memory.cnt); - pr_debug(" memory.size = 0x%llx\n", + if (!lmb_debug) + return; + + pr_info("lmb_dump_all:\n"); + pr_info(" memory.cnt = 0x%lx\n", lmb.memory.cnt); + pr_info(" memory.size = 0x%llx\n", (unsigned long long)lmb.memory.size); for (i=0; i < lmb.memory.cnt ;i++) { - pr_debug(" memory.region[0x%x].base = 0x%llx\n", + pr_info(" memory.region[0x%lx].base = 0x%llx\n", i, (unsigned long long)lmb.memory.region[i].base); - pr_debug(" .size = 0x%llx\n", + pr_info(" .size = 0x%llx\n", (unsigned long long)lmb.memory.region[i].size); } - pr_debug(" reserved.cnt = 0x%lx\n", lmb.reserved.cnt); - pr_debug(" reserved.size = 0x%lx\n", lmb.reserved.size); + pr_info(" reserved.cnt = 0x%lx\n", lmb.reserved.cnt); + pr_info(" reserved.size = 0x%lx\n", lmb.reserved.size); for (i=0; i < lmb.reserved.cnt ;i++) { - pr_debug(" reserved.region[0x%x].base = 0x%llx\n", + pr_info(" reserved.region[0x%lx].base = 0x%llx\n", i, (unsigned long long)lmb.reserved.region[i].base); - pr_debug(" .size = 0x%llx\n", + pr_info(" .size = 0x%llx\n", (unsigned long long)lmb.reserved.region[i].size); } -#endif /* DEBUG */ } static unsigned long lmb_addrs_overlap(u64 base1, u64 size1, u64 base2, -- cgit v1.1 From 85b442e378ac3413e269a70a0031727ef121bd2a Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 22 Apr 2008 14:03:32 -0400 Subject: prism54: fix regression with missing carrier in AP-mode This fixes a regression introduced by commit 7b463ced6 (prism54: set carrier flags correctly) which causes the device to come up without a carrier in AP-mode. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/prism54/islpci_dev.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 04c2638..9196825 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -388,8 +388,15 @@ islpci_open(struct net_device *ndev) netif_start_queue(ndev); - /* Turn off carrier unless we know we have associated */ - netif_carrier_off(ndev); + /* Turn off carrier if in STA or Ad-hoc mode. It will be turned on + * once the firmware receives a trap of being associated + * (GEN_OID_LINKSTATE). In other modes (AP or WDS or monitor) we + * should just leave the carrier on as its expected the firmware + * won't send us a trigger. */ + if (priv->iw_mode == IW_MODE_INFRA || priv->iw_mode == IW_MODE_ADHOC) + netif_carrier_off(ndev); + else + netif_carrier_on(ndev); return 0; } -- cgit v1.1 From bb55bdd512905f35f9d7dfe65d1f16014e1f9b2f Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Thu, 1 May 2008 15:58:17 -0700 Subject: fix irq flags in mac80211 code A file in the net/mac80211 directory uses "int" for flags. This can cause hard to find bugs on some architectures. This patch converts the flags to use "long" instead. This bug was discovered by doing an allyesconfig make on the -rt kernel where checks are done to ensure all flags are of size sizeof(long). Signed-off-by: Steven Rostedt Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- net/mac80211/rc80211_pid_debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c index ae75d41..ff5c380f 100644 --- a/net/mac80211/rc80211_pid_debugfs.c +++ b/net/mac80211/rc80211_pid_debugfs.c @@ -85,7 +85,7 @@ static int rate_control_pid_events_open(struct inode *inode, struct file *file) struct rc_pid_sta_info *sinfo = inode->i_private; struct rc_pid_event_buffer *events = &sinfo->events; struct rc_pid_events_file_info *file_info; - unsigned int status; + unsigned long status; /* Allocate a state struct */ file_info = kmalloc(sizeof(*file_info), GFP_KERNEL); @@ -135,7 +135,7 @@ static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf, char pb[RC_PID_PRINT_BUF_SIZE]; int ret; int p; - unsigned int status; + unsigned long status; /* Check if there is something to read. */ if (events->next_entry == file_info->next_entry) { -- cgit v1.1 From d5251aea1539ec89dd567e75169c568b5243b6fa Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 2 May 2008 09:56:34 -0400 Subject: wavelan: avoid index past end of array if DEBUG_SHOW_UNUSED is defined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reported by Daniel Marjamäki here: http://bugzilla.kernel.org/show_bug.cgi?id=10588 Signed-off-by: John W. Linville --- drivers/net/wireless/wavelan.c | 4 ++-- drivers/net/wireless/wavelan_cs.c | 6 ++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c index 03384a4..49ae970 100644 --- a/drivers/net/wireless/wavelan.c +++ b/drivers/net/wireless/wavelan.c @@ -908,9 +908,9 @@ static void wv_psa_show(psa_t * p) p->psa_call_code[3], p->psa_call_code[4], p->psa_call_code[5], p->psa_call_code[6], p->psa_call_code[7]); #ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "psa_reserved[]: %02X:%02X:%02X:%02X\n", + printk(KERN_DEBUG "psa_reserved[]: %02X:%02X\n", p->psa_reserved[0], - p->psa_reserved[1], p->psa_reserved[2], p->psa_reserved[3]); + p->psa_reserved[1]); #endif /* DEBUG_SHOW_UNUSED */ printk(KERN_DEBUG "psa_conf_status: %d, ", p->psa_conf_status); printk("psa_crc: 0x%02x%02x, ", p->psa_crc[0], p->psa_crc[1]); diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c index baf7401..b584c0e 100644 --- a/drivers/net/wireless/wavelan_cs.c +++ b/drivers/net/wireless/wavelan_cs.c @@ -1074,11 +1074,9 @@ wv_psa_show(psa_t * p) p->psa_call_code[6], p->psa_call_code[7]); #ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "psa_reserved[]: %02X:%02X:%02X:%02X\n", + printk(KERN_DEBUG "psa_reserved[]: %02X:%02X\n", p->psa_reserved[0], - p->psa_reserved[1], - p->psa_reserved[2], - p->psa_reserved[3]); + p->psa_reserved[1]); #endif /* DEBUG_SHOW_UNUSED */ printk(KERN_DEBUG "psa_conf_status: %d, ", p->psa_conf_status); printk("psa_crc: 0x%02x%02x, ", p->psa_crc[0], p->psa_crc[1]); -- cgit v1.1 From 78520cad4b222d81fa18f2dcfa52394d8d1722b0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Sat, 3 May 2008 01:04:47 +0200 Subject: mac80211: fix debugfs default key oops Under certain circumstances (in AP mode) the debugfs function that is supposed to add the default key symlink can encounter a NULL default_key pointer. This patch makes it handle that situtation gracefully. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- net/mac80211/debugfs_key.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/net/mac80211/debugfs_key.c b/net/mac80211/debugfs_key.c index 879e721..19efc3a 100644 --- a/net/mac80211/debugfs_key.c +++ b/net/mac80211/debugfs_key.c @@ -255,14 +255,23 @@ void ieee80211_debugfs_key_remove(struct ieee80211_key *key) void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata) { char buf[50]; + struct ieee80211_key *key; if (!sdata->debugfsdir) return; - sprintf(buf, "../keys/%d", sdata->default_key->debugfs.cnt); - sdata->debugfs.default_key = - debugfs_create_symlink("default_key", sdata->debugfsdir, buf); + /* this is running under the key lock */ + + key = sdata->default_key; + if (key) { + sprintf(buf, "../keys/%d", key->debugfs.cnt); + sdata->debugfs.default_key = + debugfs_create_symlink("default_key", + sdata->debugfsdir, buf); + } else + ieee80211_debugfs_key_remove_default(sdata); } + void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata) { if (!sdata) -- cgit v1.1 From 6243065d308ab566aa318a8adef853bc0418896d Mon Sep 17 00:00:00 2001 From: Zhu Yi Date: Mon, 5 May 2008 10:22:46 +0800 Subject: iwlwifi: fix compile error when CONFIG_MAC80211_DEBUGFS is not selected Make iwl4965_lq_sta->drv available even without CONFIG_MAC80211_DEBUGFS. Signed-off-by: Yi Zhu Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965-rs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c index b608e1c..c9847b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965-rs.c @@ -163,8 +163,8 @@ struct iwl4965_lq_sta { struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; #endif struct iwl4965_rate dbg_fixed; - struct iwl_priv *drv; #endif + struct iwl_priv *drv; }; static void rs_rate_scale_perform(struct iwl_priv *priv, -- cgit v1.1 From 78720897459a0ed3843c80e9bd9ef1b2f7ae5c8f Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 5 May 2008 17:23:31 +0200 Subject: rt2x00: Don't use pskb_expand_head() rt2x00pci allocates DMA for descriptor and data, rt61pci doesn't use this for the beacon, but it can use the descriptor part as temporary buffer instead of using pskb_expand_head(). Using this temporary buffer is obviously much better then reallocating the skb buffer... At the same time we can set the data length for the beacon queue at 0, to make sure no DMA is allocated for data (but just for the descriptor). Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt61pci.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c index ae12dcd..14bc7b2 100644 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ b/drivers/net/wireless/rt2x00/rt61pci.c @@ -2366,6 +2366,7 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, { struct rt2x00_dev *rt2x00dev = hw->priv; struct rt2x00_intf *intf = vif_to_intf(control->vif); + struct queue_entry_priv_pci_tx *priv_tx; struct skb_frame_desc *skbdesc; unsigned int beacon_base; u32 reg; @@ -2373,21 +2374,8 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, if (unlikely(!intf->beacon)) return -ENOBUFS; - /* - * We need to append the descriptor in front of the - * beacon frame. - */ - if (skb_headroom(skb) < intf->beacon->queue->desc_size) { - if (pskb_expand_head(skb, intf->beacon->queue->desc_size, - 0, GFP_ATOMIC)) - return -ENOMEM; - } - - /* - * Add the descriptor in front of the skb. - */ - skb_push(skb, intf->beacon->queue->desc_size); - memset(skb->data, 0, intf->beacon->queue->desc_size); + priv_tx = intf->beacon->priv_data; + memset(priv_tx->desc, 0, intf->beacon->queue->desc_size); /* * Fill in skb descriptor @@ -2395,9 +2383,9 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, skbdesc = get_skb_frame_desc(skb); memset(skbdesc, 0, sizeof(*skbdesc)); skbdesc->flags |= FRAME_DESC_DRIVER_GENERATED; - skbdesc->data = skb->data + intf->beacon->queue->desc_size; - skbdesc->data_len = skb->len - intf->beacon->queue->desc_size; - skbdesc->desc = skb->data; + skbdesc->data = skb->data; + skbdesc->data_len = skb->len; + skbdesc->desc = priv_tx->desc; skbdesc->desc_len = intf->beacon->queue->desc_size; skbdesc->entry = intf->beacon; @@ -2425,7 +2413,10 @@ static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb, */ beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); rt2x00pci_register_multiwrite(rt2x00dev, beacon_base, - skb->data, skb->len); + skbdesc->desc, skbdesc->desc_len); + rt2x00pci_register_multiwrite(rt2x00dev, + beacon_base + skbdesc->desc_len, + skbdesc->data, skbdesc->data_len); rt61pci_kick_tx_queue(rt2x00dev, control->queue); return 0; @@ -2490,7 +2481,7 @@ static const struct data_queue_desc rt61pci_queue_tx = { static const struct data_queue_desc rt61pci_queue_bcn = { .entry_num = 4 * BEACON_ENTRIES, - .data_size = MGMT_FRAME_SIZE, + .data_size = 0, /* No DMA required for beacons */ .desc_size = TXINFO_SIZE, .priv_size = sizeof(struct queue_entry_priv_pci_tx), }; -- cgit v1.1 From ed499983b88d138848ec9e4d104fd86a5ef0c183 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 5 May 2008 17:23:47 +0200 Subject: rt2x00: Fix broken recover-on-error path During initialization the initialize() callback function in rt2x00pci and rt2x00usb will cleanup the mess they made. rt2x00lib shouldn't call uninitialize because the callback function already cleaned up _and_ the DEVICE_INITIALIZED isn't set which causes the rt2x00lib_uninitialize() to halt directly anyway. All that is required to be cleaned up by rt2x00lib is the queue, and that can be done by calling rt2x00queue_uninitialize() directly. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00dev.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 8d8657f..b22c027 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c @@ -1032,8 +1032,10 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) * Initialize the device. */ status = rt2x00dev->ops->lib->initialize(rt2x00dev); - if (status) - goto exit; + if (status) { + rt2x00queue_uninitialize(rt2x00dev); + return status; + } __set_bit(DEVICE_INITIALIZED, &rt2x00dev->flags); @@ -1043,11 +1045,6 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) rt2x00rfkill_register(rt2x00dev); return 0; - -exit: - rt2x00lib_uninitialize(rt2x00dev); - - return status; } int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) -- cgit v1.1 From b30cdfc517b06f5d3f7a5e90626931140b2caece Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 5 May 2008 17:24:03 +0200 Subject: rt2x00: Clean up error handling of PCI queue DMA allocation. When, for some reason, the rt2x00pci module fails to allocate DMA memory for the queues, it tries to undo the complete initialization of the PCI device, including freeing of the irq. This results in the following error in dmesg, as the irq hadn't been requested yet: [ 78.123456] Trying to free already-free IRQ 17 Fix this by implementing proper error handling code, instead of just using the full uninitialization function. Signed-off-by: Gertjan van Wingerde Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00pci.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c index 7867ec6..971af25 100644 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ b/drivers/net/wireless/rt2x00/rt2x00pci.c @@ -314,13 +314,14 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) if (status) { ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", pci_dev->irq, status); - return status; + goto exit; } return 0; exit: - rt2x00pci_uninitialize(rt2x00dev); + queue_for_each(rt2x00dev, queue) + rt2x00pci_free_queue_dma(rt2x00dev, queue); return status; } -- cgit v1.1 From df44205455773852a6af10a7c6ed768fe8a86b31 Mon Sep 17 00:00:00 2001 From: Ivo van Doorn Date: Mon, 5 May 2008 20:40:35 +0200 Subject: mac80211: Don't encrypt beacons mac80211 should set the IEEE80211_TX_CTL_DO_NOT_ENCRYPT flag in tx_control structure to inform drivers not to encrypt the beacon. Drivers that only check for that flag before accessing the hw_key field, will otherwise cause a NULL pointer dereference since that field is not configured for beacons. Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- net/mac80211/tx.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index f35eaea9..28d8bd5 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1898,6 +1898,7 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw, control->flags |= IEEE80211_TXCTL_SHORT_PREAMBLE; control->antenna_sel_tx = local->hw.conf.antenna_sel_tx; control->flags |= IEEE80211_TXCTL_NO_ACK; + control->flags |= IEEE80211_TXCTL_DO_NOT_ENCRYPT; control->retry_limit = 1; control->flags |= IEEE80211_TXCTL_CLEAR_PS_FILT; } -- cgit v1.1 From ef269254772a0d2253c85cafe160e3f6528eb292 Mon Sep 17 00:00:00 2001 From: Luis Carlos Cobo Date: Mon, 5 May 2008 12:02:35 -0700 Subject: mac80211: fix incorrect mesh header length This should have been updated at the same time we were transitioning from 3 byte to 4 byte mesh sequence number. Pointed out by Johannes Berg. Signed-off-by: Luis Carlos Cobo Signed-off-by: John W. Linville --- net/mac80211/mesh.c | 2 +- net/mac80211/util.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index f76bc26..697ef67 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c @@ -397,7 +397,7 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, put_unaligned(cpu_to_le32(sdata->u.sta.mesh_seqnum), &meshhdr->seqnum); sdata->u.sta.mesh_seqnum++; - return 5; + return 6; } void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index cc9f715..24a465c 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -153,15 +153,15 @@ int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) /* 7.1.3.5a.2 */ switch (ae) { case 0: - return 5; + return 6; case 1: - return 11; + return 12; case 2: - return 17; + return 18; case 3: - return 23; + return 24; default: - return 5; + return 6; } } -- cgit v1.1 From 69687a0b9934942e61bf8148c242adea87183a5b Mon Sep 17 00:00:00 2001 From: Luis Carlos Cobo Date: Mon, 5 May 2008 12:29:42 -0700 Subject: mac80211: fix access to null skb Without this patch, if xmit_skb is null but net_ratelimit() returns 0 we would go to the else branch and access the null xmit_skb. Pointed out by Johannes Berg. Signed-off-by: Luis Carlos Cobo Signed-off-by: John W. Linville --- net/mac80211/rx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 02f436a..9c57b3a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1305,11 +1305,11 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) if (is_multicast_ether_addr(skb->data)) { if (*mesh_ttl > 0) { xmit_skb = skb_copy(skb, GFP_ATOMIC); - if (!xmit_skb && net_ratelimit()) + if (xmit_skb) + xmit_skb->pkt_type = PACKET_OTHERHOST; + else if (net_ratelimit()) printk(KERN_DEBUG "%s: failed to clone " "multicast frame\n", dev->name); - else - xmit_skb->pkt_type = PACKET_OTHERHOST; } else IEEE80211_IFSTA_MESH_CTR_INC(&sdata->u.sta, dropped_frames_ttl); -- cgit v1.1 From 812714d741750038004da505074c9158e9dee270 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 6 May 2008 12:52:07 +0200 Subject: mac80211: mesh hwmp: fix kfree(skb) Signed-off-by: Patrick McHardy Signed-off-by: John W. Linville --- net/mac80211/mesh_hwmp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 3df8092..af0cd1e 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -120,7 +120,7 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, *pos++ = WLAN_EID_PREP; break; default: - kfree(skb); + kfree_skb(skb); return -ENOTSUPP; break; } -- cgit v1.1 From f84e71a94cb5f88d86ab50c251e09379925b80b9 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 6 May 2008 18:46:36 +0400 Subject: Fix GFP_KERNEL allocation under read lock. The mesh_path_add() read-locks the pathtbl_resize_lock and calls kmalloc with GFP_KERNEL mask. Fix it and move the endadd2 label lower. It should be _before_ the if() beyond, but it makes no sense for it being there, so I move it right after this if(). Signed-off-by: Pavel Emelyanov Signed-off-by: John W. Linville --- net/mac80211/mesh_pathtbl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 5845dc2..727aa52 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -158,14 +158,14 @@ int mesh_path_add(u8 *dst, struct net_device *dev) if (atomic_add_unless(&sdata->u.sta.mpaths, 1, MESH_MAX_MPATHS) == 0) return -ENOSPC; - read_lock(&pathtbl_resize_lock); - new_mpath = kzalloc(sizeof(struct mesh_path), GFP_KERNEL); if (!new_mpath) { atomic_dec(&sdata->u.sta.mpaths); err = -ENOMEM; goto endadd2; } + + read_lock(&pathtbl_resize_lock); memcpy(new_mpath->dst, dst, ETH_ALEN); new_mpath->dev = dev; new_mpath->flags = 0; @@ -202,7 +202,6 @@ int mesh_path_add(u8 *dst, struct net_device *dev) endadd: spin_unlock(&mesh_paths->hashwlock[hash_idx]); -endadd2: read_unlock(&pathtbl_resize_lock); if (!err && grow) { struct mesh_table *oldtbl, *newtbl; @@ -219,6 +218,7 @@ endadd2: mesh_table_free(oldtbl, false); write_unlock(&pathtbl_resize_lock); } +endadd2: return err; } -- cgit v1.1 From 0eb03d5a14377eecf6ed0ebf3cc2c9f48c12c7c6 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 6 May 2008 18:49:02 +0400 Subject: Fix not checked kmalloc() result. The new_node kmallocation is not checked for success, so add this check. BTW, it also happens under the read_lock. Signed-off-by: Pavel Emelyanov Signed-off-by: John W. Linville --- net/mac80211/mesh_pathtbl.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 727aa52..1d2d051 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -164,13 +164,19 @@ int mesh_path_add(u8 *dst, struct net_device *dev) err = -ENOMEM; goto endadd2; } + new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); + if (!new_node) { + kfree(new_mpath); + atomic_dec(&sdata->u.sta.mpaths); + err = -ENOMEM; + goto endadd2; + } read_lock(&pathtbl_resize_lock); memcpy(new_mpath->dst, dst, ETH_ALEN); new_mpath->dev = dev; new_mpath->flags = 0; skb_queue_head_init(&new_mpath->frame_queue); - new_node = kmalloc(sizeof(struct mpath_node), GFP_KERNEL); new_node->mpath = new_mpath; new_mpath->timer.data = (unsigned long) new_mpath; new_mpath->timer.function = mesh_path_timer; -- cgit v1.1 From 6d6936e2ea82ebcbdd12d489b7b5ccf430de52f1 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 6 May 2008 18:51:31 +0400 Subject: Fix potential scheduling while atomic in mesh_path_add. Calling synchronize_rcu() under write-lock-ed pathtbl_resize_lock may result in this warning (and other side effects). It looks safe just dropping this lock before calling synchronize_rcu. Signed-off-by: Pavel Emelyanov Signed-off-by: John W. Linville --- net/mac80211/mesh_pathtbl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 1d2d051..99c2d36 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -220,9 +220,10 @@ endadd: return -ENOMEM; } rcu_assign_pointer(mesh_paths, newtbl); + write_unlock(&pathtbl_resize_lock); + synchronize_rcu(); mesh_table_free(oldtbl, false); - write_unlock(&pathtbl_resize_lock); } endadd2: return err; -- cgit v1.1 From dbabad0c9c026dea3ba803cbd9d768cdffc68e32 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 8 May 2008 01:43:59 +0200 Subject: zd1211rw: fix potential use-after-free bug zd_mac_tx_to_dev() could potentially free the skb, or hand it off to mac80211 which might free it. Hence, this code needs to get the usb pointer out of skb->cb before handing it off to that function. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_usb.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c index 5316074..12e24f0 100644 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ b/drivers/net/wireless/zd1211rw/zd_usb.c @@ -889,9 +889,13 @@ static void tx_urb_complete(struct urb *urb) } free_urb: skb = (struct sk_buff *)urb->context; - zd_mac_tx_to_dev(skb, urb->status); + /* + * grab 'usb' pointer before handing off the skb (since + * it might be freed by zd_mac_tx_to_dev or mac80211) + */ cb = (struct zd_tx_skb_control_block *)skb->cb; usb = &zd_hw_mac(cb->hw)->chip.usb; + zd_mac_tx_to_dev(skb, urb->status); free_tx_urb(usb, urb); tx_dec_submitted_urbs(usb); return; -- cgit v1.1 From c0186078b78839a8bdb385fa07a816c2f348a49d Mon Sep 17 00:00:00 2001 From: Emmanuel Grumbach Date: Thu, 8 May 2008 11:34:05 +0800 Subject: iwlwifi: Fix frequency in rx_status fill This patch fixes a bug in RX path, the frequency was wrongly set in the ieee80211_rx_status. This bug led to an empty scan list in A band. Signed-off-by: Emmanuel Grumbach Signed-off-by: Tomas Winkler Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-3945.c | 2 +- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index d340683..62a3d8f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -666,7 +666,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv, rx_status.flag = 0; rx_status.mactime = le64_to_cpu(rx_end->timestamp); rx_status.freq = - ieee80211_frequency_to_channel(le16_to_cpu(rx_hdr->channel)); + ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel)); rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 17f629f..bf19eb8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -3978,7 +3978,7 @@ static void iwl4965_rx_reply_rx(struct iwl_priv *priv, rx_status.mactime = le64_to_cpu(rx_start->timestamp); rx_status.freq = - ieee80211_frequency_to_channel(le16_to_cpu(rx_start->channel)); + ieee80211_channel_to_frequency(le16_to_cpu(rx_start->channel)); rx_status.band = (rx_start->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; rx_status.rate_idx = -- cgit v1.1 From 36d16ae73becc5978fe22866e9ab66b509211afe Mon Sep 17 00:00:00 2001 From: Helmut Schaa Date: Thu, 8 May 2008 13:34:07 +0200 Subject: mac80211: fix association with some APs Some APs refuse association if the supported rates contained in the association request do not match its own supported rates. This patch introduces a new function which builds the intersection between the AP's supported rates and the client's supported rates to work around such problems. The same approach is already used in ipw2200 for example. Signed-off-by: Helmut Schaa Signed-off-by: John W. Linville --- net/mac80211/mlme.c | 64 +++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 14 deletions(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a5e5c31..4adba09 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -665,6 +665,26 @@ static void ieee80211_authenticate(struct net_device *dev, mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); } +static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss, + struct ieee80211_supported_band *sband, + u64 *rates) +{ + int i, j, count; + *rates = 0; + count = 0; + for (i = 0; i < bss->supp_rates_len; i++) { + int rate = (bss->supp_rates[i] & 0x7F) * 5; + + for (j = 0; j < sband->n_bitrates; j++) + if (sband->bitrates[j].bitrate == rate) { + *rates |= BIT(j); + count++; + break; + } + } + + return count; +} static void ieee80211_send_assoc(struct net_device *dev, struct ieee80211_if_sta *ifsta) @@ -673,11 +693,12 @@ static void ieee80211_send_assoc(struct net_device *dev, struct sk_buff *skb; struct ieee80211_mgmt *mgmt; u8 *pos, *ies; - int i, len; + int i, len, count, rates_len, supp_rates_len; u16 capab; struct ieee80211_sta_bss *bss; int wmm = 0; struct ieee80211_supported_band *sband; + u64 rates = 0; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + ifsta->extra_ie_len + @@ -740,24 +761,39 @@ static void ieee80211_send_assoc(struct net_device *dev, *pos++ = ifsta->ssid_len; memcpy(pos, ifsta->ssid, ifsta->ssid_len); + /* all supported rates should be added here but some APs + * (e.g. D-Link DAP 1353 in b-only mode) don't like that + * Therefore only add rates the AP supports */ + rates_len = ieee80211_compatible_rates(bss, sband, &rates); + supp_rates_len = rates_len; + if (supp_rates_len > 8) + supp_rates_len = 8; + len = sband->n_bitrates; - if (len > 8) - len = 8; - pos = skb_put(skb, len + 2); + pos = skb_put(skb, supp_rates_len + 2); *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = len; - for (i = 0; i < len; i++) { - int rate = sband->bitrates[i].bitrate; - *pos++ = (u8) (rate / 5); - } + *pos++ = supp_rates_len; - if (sband->n_bitrates > len) { - pos = skb_put(skb, sband->n_bitrates - len + 2); - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = sband->n_bitrates - len; - for (i = len; i < sband->n_bitrates; i++) { + count = 0; + for (i = 0; i < sband->n_bitrates; i++) { + if (BIT(i) & rates) { int rate = sband->bitrates[i].bitrate; *pos++ = (u8) (rate / 5); + if (++count == 8) + break; + } + } + + if (count == 8) { + pos = skb_put(skb, rates_len - count + 2); + *pos++ = WLAN_EID_EXT_SUPP_RATES; + *pos++ = rates_len - count; + + for (i++; i < sband->n_bitrates; i++) { + if (BIT(i) & rates) { + int rate = sband->bitrates[i].bitrate; + *pos++ = (u8) (rate / 5); + } } } -- cgit v1.1 From 6fc7431dc0775f21ad7a7a39c2ad0290291a56ea Mon Sep 17 00:00:00 2001 From: Masakazu Mokuno Date: Mon, 12 May 2008 13:50:28 +0900 Subject: PS3: gelic: fix memory leak This fixes the bug that the I/O buffer is not freed at the driver removal. Signed-off-by: Masakazu Mokuno Signed-off-by: John W. Linville --- drivers/net/ps3_gelic_wireless.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ps3_gelic_wireless.c b/drivers/net/ps3_gelic_wireless.c index 0d32123..1dae1f2 100644 --- a/drivers/net/ps3_gelic_wireless.c +++ b/drivers/net/ps3_gelic_wireless.c @@ -2474,6 +2474,8 @@ static void gelic_wl_free(struct gelic_wl_info *wl) pr_debug("%s: <-\n", __func__); + free_page((unsigned long)wl->buf); + pr_debug("%s: destroy queues\n", __func__); destroy_workqueue(wl->eurus_cmd_queue); destroy_workqueue(wl->event_queue); -- cgit v1.1 From a4278e18e7e497b76781492d010035c3c36f7403 Mon Sep 17 00:00:00 2001 From: Pavel Roskin Date: Mon, 12 May 2008 09:02:24 -0400 Subject: mac80211: add missing newlines in printk() Signed-off-by: Pavel Roskin Signed-off-by: John W. Linville --- net/mac80211/rx.c | 6 +++--- net/mac80211/wme.c | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 9c57b3a..1958bfb3 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1395,7 +1395,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) padding = ((4 - subframe_len) & 0x3); /* the last MSDU has no padding */ if (subframe_len > remaining) { - printk(KERN_DEBUG "%s: wrong buffer size", dev->name); + printk(KERN_DEBUG "%s: wrong buffer size\n", dev->name); return RX_DROP_UNUSABLE; } @@ -1418,7 +1418,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx) eth = (struct ethhdr *) skb_pull(skb, ntohs(len) + padding); if (!eth) { - printk(KERN_DEBUG "%s: wrong buffer size ", + printk(KERN_DEBUG "%s: wrong buffer size\n", dev->name); dev_kfree_skb(frame); return RX_DROP_UNUSABLE; @@ -1952,7 +1952,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, if (!skb_new) { if (net_ratelimit()) printk(KERN_DEBUG "%s: failed to copy " - "multicast frame for %s", + "multicast frame for %s\n", wiphy_name(local->hw.wiphy), prev->dev->name); continue; diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c index 64faa3d..dc1598b8 100644 --- a/net/mac80211/wme.c +++ b/net/mac80211/wme.c @@ -394,7 +394,8 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct nlattr *opt) qd->handle); if (!q->queues[i]) { q->queues[i] = &noop_qdisc; - printk(KERN_ERR "%s child qdisc %i creation failed", dev->name, i); + printk(KERN_ERR "%s child qdisc %i creation failed\n", + dev->name, i); } } -- cgit v1.1 From 8388e3da34edb141362bb42811ee487dfec15525 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 12 May 2008 20:17:33 -0700 Subject: net: Set LL_MAX_HEADER properly for wireless. Wireless networking, particularly with MESH enabled, has quite strong requirements for link-layer header space. Based upon some numbers and descriptions from Johannes Berg we use 96 (same as AX25) for plain wireless, and with mesh enabled we use 128. In the process, simplify the cpp conditional logic here by ordering the cases by those needing the most space down to those needing the least case. Signed-off-by: David S. Miller --- include/linux/netdevice.h | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 7469017..a3fb57f 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -93,14 +93,16 @@ struct wireless_dev; * used. */ -#if !defined(CONFIG_AX25) && !defined(CONFIG_AX25_MODULE) && !defined(CONFIG_TR) -#define LL_MAX_HEADER 32 +#if defined(CONFIG_WLAN_80211) || defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) +# if defined(CONFIG_MAC80211_MESH) +# define LL_MAX_HEADER 128 +# else +# define LL_MAX_HEADER 96 +# endif +#elif defined(CONFIG_TR) +# define LL_MAX_HEADER 48 #else -#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE) -#define LL_MAX_HEADER 96 -#else -#define LL_MAX_HEADER 48 -#endif +# define LL_MAX_HEADER 32 #endif #if !defined(CONFIG_NET_IPIP) && !defined(CONFIG_NET_IPIP_MODULE) && \ -- cgit v1.1 From f5184d267c1aedb9b7a8cc44e08ff6b8d382c3b5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 12 May 2008 20:48:31 -0700 Subject: net: Allow netdevices to specify needed head/tailroom This patch adds needed_headroom/needed_tailroom members to struct net_device and updates many places that allocate sbks to use them. Not all of them can be converted though, and I'm sure I missed some (I mostly grepped for LL_RESERVED_SPACE) Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- include/linux/netdevice.h | 16 ++++++++++++++-- net/core/netpoll.c | 2 +- net/econet/af_econet.c | 2 +- net/ipv4/arp.c | 2 +- net/ipv4/igmp.c | 4 ++-- net/ipv4/ipconfig.c | 6 +++--- net/ipv4/raw.c | 10 ++++------ net/ipv6/ip6_output.c | 2 +- net/ipv6/mcast.c | 4 ++-- net/ipv6/ndisc.c | 4 ++-- net/ipv6/raw.c | 10 ++++------ net/packet/af_packet.c | 2 +- net/xfrm/xfrm_output.c | 6 +++--- 13 files changed, 39 insertions(+), 31 deletions(-) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index a3fb57f..b11e6e1 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -246,11 +246,16 @@ struct hh_cache * * We could use other alignment values, but we must maintain the * relationship HH alignment <= LL alignment. + * + * LL_ALLOCATED_SPACE also takes into account the tailroom the device + * may need. */ #define LL_RESERVED_SPACE(dev) \ - (((dev)->hard_header_len&~(HH_DATA_MOD - 1)) + HH_DATA_MOD) + ((((dev)->hard_header_len+(dev)->needed_headroom)&~(HH_DATA_MOD - 1)) + HH_DATA_MOD) #define LL_RESERVED_SPACE_EXTRA(dev,extra) \ - ((((dev)->hard_header_len+extra)&~(HH_DATA_MOD - 1)) + HH_DATA_MOD) + ((((dev)->hard_header_len+(dev)->needed_headroom+(extra))&~(HH_DATA_MOD - 1)) + HH_DATA_MOD) +#define LL_ALLOCATED_SPACE(dev) \ + ((((dev)->hard_header_len+(dev)->needed_headroom+(dev)->needed_tailroom)&~(HH_DATA_MOD - 1)) + HH_DATA_MOD) struct header_ops { int (*create) (struct sk_buff *skb, struct net_device *dev, @@ -569,6 +574,13 @@ struct net_device unsigned short type; /* interface hardware type */ unsigned short hard_header_len; /* hardware hdr length */ + /* extra head- and tailroom the hardware may need, but not in all cases + * can this be guaranteed, especially tailroom. Some cases also use + * LL_MAX_HEADER instead to allocate the skb. + */ + unsigned short needed_headroom; + unsigned short needed_tailroom; + struct net_device *master; /* Pointer to master device of a group, * which this device is member of. */ diff --git a/net/core/netpoll.c b/net/core/netpoll.c index b04d643..8fb134d 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c @@ -419,7 +419,7 @@ static void arp_reply(struct sk_buff *skb) return; size = arp_hdr_len(skb->dev); - send_skb = find_skb(np, size + LL_RESERVED_SPACE(np->dev), + send_skb = find_skb(np, size + LL_ALLOCATED_SPACE(np->dev), LL_RESERVED_SPACE(np->dev)); if (!send_skb) diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 68d1544..7c9bb13 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -340,7 +340,7 @@ static int econet_sendmsg(struct kiocb *iocb, struct socket *sock, dev_hold(dev); - skb = sock_alloc_send_skb(sk, len+LL_RESERVED_SPACE(dev), + skb = sock_alloc_send_skb(sk, len+LL_ALLOCATED_SPACE(dev), msg->msg_flags & MSG_DONTWAIT, &err); if (skb==NULL) goto out_unlock; diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c index 68b72a7..418862f 100644 --- a/net/ipv4/arp.c +++ b/net/ipv4/arp.c @@ -570,7 +570,7 @@ struct sk_buff *arp_create(int type, int ptype, __be32 dest_ip, * Allocate a buffer */ - skb = alloc_skb(arp_hdr_len(dev) + LL_RESERVED_SPACE(dev), GFP_ATOMIC); + skb = alloc_skb(arp_hdr_len(dev) + LL_ALLOCATED_SPACE(dev), GFP_ATOMIC); if (skb == NULL) return NULL; diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 6250f42..2769dc4 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c @@ -292,7 +292,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) struct iphdr *pip; struct igmpv3_report *pig; - skb = alloc_skb(size + LL_RESERVED_SPACE(dev), GFP_ATOMIC); + skb = alloc_skb(size + LL_ALLOCATED_SPACE(dev), GFP_ATOMIC); if (skb == NULL) return NULL; @@ -653,7 +653,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, return -1; } - skb=alloc_skb(IGMP_SIZE+LL_RESERVED_SPACE(dev), GFP_ATOMIC); + skb=alloc_skb(IGMP_SIZE+LL_ALLOCATED_SPACE(dev), GFP_ATOMIC); if (skb == NULL) { ip_rt_put(rt); return -1; diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 89dee43..ed45037 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c @@ -710,14 +710,14 @@ static void __init ic_bootp_send_if(struct ic_device *d, unsigned long jiffies_d struct net_device *dev = d->dev; struct sk_buff *skb; struct bootp_pkt *b; - int hh_len = LL_RESERVED_SPACE(dev); struct iphdr *h; /* Allocate packet */ - skb = alloc_skb(sizeof(struct bootp_pkt) + hh_len + 15, GFP_KERNEL); + skb = alloc_skb(sizeof(struct bootp_pkt) + LL_ALLOCATED_SPACE(dev) + 15, + GFP_KERNEL); if (!skb) return; - skb_reserve(skb, hh_len); + skb_reserve(skb, LL_RESERVED_SPACE(dev)); b = (struct bootp_pkt *) skb_put(skb, sizeof(struct bootp_pkt)); memset(b, 0, sizeof(struct bootp_pkt)); diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 11d7f75..fead049 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -322,7 +322,6 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, unsigned int flags) { struct inet_sock *inet = inet_sk(sk); - int hh_len; struct iphdr *iph; struct sk_buff *skb; unsigned int iphlen; @@ -336,13 +335,12 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, if (flags&MSG_PROBE) goto out; - hh_len = LL_RESERVED_SPACE(rt->u.dst.dev); - - skb = sock_alloc_send_skb(sk, length+hh_len+15, - flags&MSG_DONTWAIT, &err); + skb = sock_alloc_send_skb(sk, + length + LL_ALLOCATED_SPACE(rt->u.dst.dev) + 15, + flags & MSG_DONTWAIT, &err); if (skb == NULL) goto error; - skb_reserve(skb, hh_len); + skb_reserve(skb, LL_RESERVED_SPACE(rt->u.dst.dev)); skb->priority = sk->sk_priority; skb->mark = sk->sk_mark; diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 0af2e05..48cdce9 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -780,7 +780,7 @@ slow_path: * Allocate buffer. */ - if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_RESERVED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { + if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->u.dst.dev), GFP_ATOMIC)) == NULL) { NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); IP6_INC_STATS(ip6_dst_idev(skb->dst), IPSTATS_MIB_FRAGFAILS); diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 54f91ef..fd632dd 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -1411,7 +1411,7 @@ static struct sk_buff *mld_newpack(struct net_device *dev, int size) IPV6_TLV_PADN, 0 }; /* we assume size > sizeof(ra) here */ - skb = sock_alloc_send_skb(sk, size + LL_RESERVED_SPACE(dev), 1, &err); + skb = sock_alloc_send_skb(sk, size + LL_ALLOCATED_SPACE(dev), 1, &err); if (!skb) return NULL; @@ -1790,7 +1790,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) payload_len = len + sizeof(ra); full_len = sizeof(struct ipv6hdr) + payload_len; - skb = sock_alloc_send_skb(sk, LL_RESERVED_SPACE(dev) + full_len, 1, &err); + skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + full_len, 1, &err); if (skb == NULL) { rcu_read_lock(); diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 2c74885..a55fc05 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c @@ -479,7 +479,7 @@ static void __ndisc_send(struct net_device *dev, skb = sock_alloc_send_skb(sk, (MAX_HEADER + sizeof(struct ipv6hdr) + - len + LL_RESERVED_SPACE(dev)), + len + LL_ALLOCATED_SPACE(dev)), 1, &err); if (!skb) { ND_PRINTK0(KERN_ERR @@ -1521,7 +1521,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, buff = sock_alloc_send_skb(sk, (MAX_HEADER + sizeof(struct ipv6hdr) + - len + LL_RESERVED_SPACE(dev)), + len + LL_ALLOCATED_SPACE(dev)), 1, &err); if (buff == NULL) { ND_PRINTK0(KERN_ERR diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 396f0ea..232e0dc 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -609,7 +609,6 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6hdr *iph; struct sk_buff *skb; - unsigned int hh_len; int err; if (length > rt->u.dst.dev->mtu) { @@ -619,13 +618,12 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, if (flags&MSG_PROBE) goto out; - hh_len = LL_RESERVED_SPACE(rt->u.dst.dev); - - skb = sock_alloc_send_skb(sk, length+hh_len+15, - flags&MSG_DONTWAIT, &err); + skb = sock_alloc_send_skb(sk, + length + LL_ALLOCATED_SPACE(rt->u.dst.dev) + 15, + flags & MSG_DONTWAIT, &err); if (skb == NULL) goto error; - skb_reserve(skb, hh_len); + skb_reserve(skb, LL_RESERVED_SPACE(rt->u.dst.dev)); skb->priority = sk->sk_priority; skb->mark = sk->sk_mark; diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 2507024..2cee87d 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -743,7 +743,7 @@ static int packet_sendmsg(struct kiocb *iocb, struct socket *sock, if (len > dev->mtu+reserve) goto out_unlock; - skb = sock_alloc_send_skb(sk, len + LL_RESERVED_SPACE(dev), + skb = sock_alloc_send_skb(sk, len + LL_ALLOCATED_SPACE(dev), msg->msg_flags & MSG_DONTWAIT, &err); if (skb==NULL) goto out_unlock; diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index 09cd9c0..3f964db 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -25,11 +25,11 @@ static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb) struct dst_entry *dst = skb->dst; int nhead = dst->header_len + LL_RESERVED_SPACE(dst->dev) - skb_headroom(skb); + int ntail = dst->dev->needed_tailroom - skb_tailroom(skb); - if (nhead > 0) - return pskb_expand_head(skb, nhead, 0, GFP_ATOMIC); + if (nhead > 0 || ntail > 0) + return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC); - /* Check tail too... */ return 0; } -- cgit v1.1 From f3994eceebf64cf356a82ffb2718ef538eb8d4f4 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 12 May 2008 20:51:44 -0700 Subject: mac80211: assign needed_headroom/tailroom for netdevs This assigns the netdev's needed_headroom/tailroom members to take advantage of pre-allocated space for 802.11 headers. Signed-off-by: Johannes Berg Signed-off-by: David S. Miller --- net/mac80211/iface.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 80954a5..06e88a5 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -54,6 +54,15 @@ int ieee80211_if_add(struct net_device *dev, const char *name, if (!ndev) return -ENOMEM; + ndev->needed_headroom = local->tx_headroom + + 4*6 /* four MAC addresses */ + + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ + + 6 /* mesh */ + + 8 /* rfc1042/bridge tunnel */ + - ETH_HLEN /* ethernet hard_header_len */ + + IEEE80211_ENCRYPT_HEADROOM; + ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; + ret = dev_alloc_name(ndev, ndev->name); if (ret < 0) goto fail; -- cgit v1.1 From 608961a5eca8d3c6bd07172febc27b5559408c5d Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 12 May 2008 21:59:32 -0700 Subject: mac80211: Use skb_header_cloned() on TX path. When skb_header_cloned() returns false you can change the headers however you like. Signed-off-by: David S. Miller --- net/mac80211/tx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 28d8bd5..1d7dd54 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1562,13 +1562,13 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, * be cloned. This could happen, e.g., with Linux bridge code passing * us broadcast frames. */ - if (head_need > 0 || skb_cloned(skb)) { + if (head_need > 0 || skb_header_cloned(skb)) { #if 0 printk(KERN_DEBUG "%s: need to reallocate buffer for %d bytes " "of headroom\n", dev->name, head_need); #endif - if (skb_cloned(skb)) + if (skb_header_cloned(skb)) I802_DEBUG_INC(local->tx_expand_skb_head_cloned); else I802_DEBUG_INC(local->tx_expand_skb_head); -- cgit v1.1 From ff772b27e5f65c1a186e9f0741f0d00ef7002799 Mon Sep 17 00:00:00 2001 From: Jay Cliburn Date: Fri, 9 May 2008 22:12:06 -0500 Subject: atl1: add PHY power save mode Using vendor-provided magic, add code to enter power save mode on the PHY. We'll need this for suspend and wake-on-lan. Signed-off-by: Jay Cliburn Signed-off-by: Jeff Garzik --- drivers/net/atlx/atl1.c | 19 ++++++++----------- drivers/net/atlx/atlx.h | 3 +++ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 0afe522..3beb44e 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -638,21 +638,18 @@ static s32 atl1_phy_leave_power_saving(struct atl1_hw *hw) } /* - *TODO: do something or get rid of this + * Force the PHY into power saving mode using vendor magic. */ #ifdef CONFIG_PM -static s32 atl1_phy_enter_power_saving(struct atl1_hw *hw) +static void atl1_phy_enter_power_saving(struct atl1_hw *hw) { -/* s32 ret_val; - * u16 phy_data; - */ + atl1_write_phy_reg(hw, MII_DBG_ADDR, 0); + atl1_write_phy_reg(hw, MII_DBG_DATA, 0x124E); + atl1_write_phy_reg(hw, MII_DBG_ADDR, 2); + atl1_write_phy_reg(hw, MII_DBG_DATA, 0x3000); + atl1_write_phy_reg(hw, MII_DBG_ADDR, 3); + atl1_write_phy_reg(hw, MII_DBG_DATA, 0); -/* - ret_val = atl1_write_phy_reg(hw, ...); - ret_val = atl1_write_phy_reg(hw, ...); - .... -*/ - return 0; } #endif diff --git a/drivers/net/atlx/atlx.h b/drivers/net/atlx/atlx.h index 3be7c09..9672188 100644 --- a/drivers/net/atlx/atlx.h +++ b/drivers/net/atlx/atlx.h @@ -460,6 +460,9 @@ MODULE_VERSION(ATLX_DRIVER_VERSION); #define MII_ATLX_PSSR_100MBS 0x4000 /* 01=100Mbs */ #define MII_ATLX_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ +#define MII_DBG_ADDR 0x1D +#define MII_DBG_DATA 0x1E + /* PCI Command Register Bit Definitions */ #define PCI_REG_COMMAND 0x04 /* PCI Command Register */ #define CMD_IO_SPACE 0x0001 -- cgit v1.1 From 08e0f1dc8388b3e134c714672c59edc2a7059430 Mon Sep 17 00:00:00 2001 From: Jay Cliburn Date: Fri, 9 May 2008 22:12:07 -0500 Subject: atl1: fix broken suspend and resume Fix atl1_suspend() and atl1_resume() so they actually work. We'll use the suspend function for wake-on-lan in addition to just suspending. Signed-off-by: Jay Cliburn Signed-off-by: Jeff Garzik --- drivers/net/atlx/atl1.c | 125 +++++++++++++++++++++++++++++++----------------- 1 file changed, 80 insertions(+), 45 deletions(-) diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 3beb44e..12fb3e5 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -2781,64 +2781,93 @@ static int atl1_suspend(struct pci_dev *pdev, pm_message_t state) struct atl1_hw *hw = &adapter->hw; u32 ctrl = 0; u32 wufc = adapter->wol; + u32 val; + int retval; + u16 speed; + u16 duplex; netif_device_detach(netdev); if (netif_running(netdev)) atl1_down(adapter); + retval = pci_save_state(pdev); + if (retval) + return retval; + atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl); - if (ctrl & BMSR_LSTATUS) + val = ctrl & BMSR_LSTATUS; + if (val) wufc &= ~ATLX_WUFC_LNKC; - /* reduce speed to 10/100M */ - if (wufc) { - atl1_phy_enter_power_saving(hw); - /* if resume, let driver to re- setup link */ - hw->phy_configured = false; - atl1_set_mac_addr(hw); - atlx_set_multi(netdev); + if (val && wufc) { + val = atl1_get_speed_and_duplex(hw, &speed, &duplex); + if (val) { + if (netif_msg_ifdown(adapter)) + dev_printk(KERN_DEBUG, &pdev->dev, + "error getting speed/duplex\n"); + goto disable_wol; + } ctrl = 0; - /* turn on magic packet wol */ - if (wufc & ATLX_WUFC_MAG) - ctrl = WOL_MAGIC_EN | WOL_MAGIC_PME_EN; - /* turn on Link change WOL */ - if (wufc & ATLX_WUFC_LNKC) - ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); + /* enable magic packet WOL */ + if (wufc & ATLX_WUFC_MAG) + ctrl |= (WOL_MAGIC_EN | WOL_MAGIC_PME_EN); iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); - - /* turn on all-multi mode if wake on multicast is enabled */ - ctrl = ioread32(hw->hw_addr + REG_MAC_CTRL); - ctrl &= ~MAC_CTRL_DBG; - ctrl &= ~MAC_CTRL_PROMIS_EN; - if (wufc & ATLX_WUFC_MC) - ctrl |= MAC_CTRL_MC_ALL_EN; - else - ctrl &= ~MAC_CTRL_MC_ALL_EN; - - /* turn on broadcast mode if wake on-BC is enabled */ - if (wufc & ATLX_WUFC_BC) + ioread32(hw->hw_addr + REG_WOL_CTRL); + + /* configure the mac */ + ctrl = MAC_CTRL_RX_EN; + ctrl |= ((u32)((speed == SPEED_1000) ? MAC_CTRL_SPEED_1000 : + MAC_CTRL_SPEED_10_100) << MAC_CTRL_SPEED_SHIFT); + if (duplex == FULL_DUPLEX) + ctrl |= MAC_CTRL_DUPLX; + ctrl |= (((u32)adapter->hw.preamble_len & + MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); + if (adapter->vlgrp) + ctrl |= MAC_CTRL_RMV_VLAN; + if (wufc & ATLX_WUFC_MAG) ctrl |= MAC_CTRL_BC_EN; - else - ctrl &= ~MAC_CTRL_BC_EN; - - /* enable RX */ - ctrl |= MAC_CTRL_RX_EN; iowrite32(ctrl, hw->hw_addr + REG_MAC_CTRL); - pci_enable_wake(pdev, PCI_D3hot, 1); - pci_enable_wake(pdev, PCI_D3cold, 1); - } else { - iowrite32(0, hw->hw_addr + REG_WOL_CTRL); - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); + ioread32(hw->hw_addr + REG_MAC_CTRL); + + /* poke the PHY */ + ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC); + ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; + iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC); + ioread32(hw->hw_addr + REG_PCIE_PHYMISC); + + pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); + goto exit; } - pci_save_state(pdev); + if (!val && wufc) { + ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN); + iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL); + ioread32(hw->hw_addr + REG_WOL_CTRL); + iowrite32(0, hw->hw_addr + REG_MAC_CTRL); + ioread32(hw->hw_addr + REG_MAC_CTRL); + hw->phy_configured = false; + pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); + goto exit; + } + +disable_wol: + iowrite32(0, hw->hw_addr + REG_WOL_CTRL); + ioread32(hw->hw_addr + REG_WOL_CTRL); + ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC); + ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; + iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC); + ioread32(hw->hw_addr + REG_PCIE_PHYMISC); + atl1_phy_enter_power_saving(hw); + hw->phy_configured = false; + pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); +exit: + if (netif_running(netdev)) + pci_disable_msi(adapter->pdev); pci_disable_device(pdev); - - pci_set_power_state(pdev, PCI_D3hot); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); return 0; } @@ -2852,20 +2881,26 @@ static int atl1_resume(struct pci_dev *pdev) pci_set_power_state(pdev, PCI_D0); pci_restore_state(pdev); - /* FIXME: check and handle */ err = pci_enable_device(pdev); + if (err) { + if (netif_msg_ifup(adapter)) + dev_printk(KERN_DEBUG, &pdev->dev, + "error enabling pci device\n"); + return err; + } + + pci_set_master(pdev); + iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL); pci_enable_wake(pdev, PCI_D3hot, 0); pci_enable_wake(pdev, PCI_D3cold, 0); - iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL); - atl1_reset(adapter); + atl1_reset_hw(&adapter->hw); + adapter->cmb.cmb->int_stats = 0; if (netif_running(netdev)) atl1_up(adapter); netif_device_attach(netdev); - atl1_via_workaround(adapter); - return 0; } #else -- cgit v1.1 From bf455a2247c6abe7d0debfbf2974514b5144ed4d Mon Sep 17 00:00:00 2001 From: Jay Cliburn Date: Fri, 9 May 2008 22:12:08 -0500 Subject: atl1: add shutdown callback Add a shutdown callback that points to atl1_suspend(). This, along with a working suspend function, fixes wake-on-lan. Tested-by: Per Olofsson Signed-off-by: Jay Cliburn Signed-off-by: Jeff Garzik --- drivers/net/atlx/atl1.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 12fb3e5..b7092a3 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -36,7 +36,6 @@ * A very incomplete list of things that need to be dealt with: * * TODO: - * Wake on LAN. * Add more ethtool functions. * Fix abstruse irq enable/disable condition described here: * http://marc.theaimsgroup.com/?l=linux-netdev&m=116398508500553&w=2 @@ -2908,6 +2907,13 @@ static int atl1_resume(struct pci_dev *pdev) #define atl1_resume NULL #endif +static void atl1_shutdown(struct pci_dev *pdev) +{ +#ifdef CONFIG_PM + atl1_suspend(pdev, PMSG_SUSPEND); +#endif +} + #ifdef CONFIG_NET_POLL_CONTROLLER static void atl1_poll_controller(struct net_device *netdev) { @@ -3154,7 +3160,8 @@ static struct pci_driver atl1_driver = { .probe = atl1_probe, .remove = __devexit_p(atl1_remove), .suspend = atl1_suspend, - .resume = atl1_resume + .resume = atl1_resume, + .shutdown = atl1_shutdown }; /* -- cgit v1.1 From e8f720fdec08daa669f46c8d76da0714f6872ccc Mon Sep 17 00:00:00 2001 From: Jay Cliburn Date: Fri, 9 May 2008 22:12:09 -0500 Subject: atl1: bump version number atl1-2.1.3. Signed-off-by: Jay Cliburn Signed-off-by: Jeff Garzik --- drivers/net/atlx/atl1.c | 2 +- drivers/net/atlx/atl1.h | 2 +- drivers/net/atlx/atlx.c | 2 +- drivers/net/atlx/atlx.h | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index b7092a3..9c2394d 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -1,7 +1,7 @@ /* * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. * Copyright(c) 2006 - 2007 Chris Snook - * Copyright(c) 2006 Jay Cliburn + * Copyright(c) 2006 - 2008 Jay Cliburn * * Derived from Intel e1000 driver * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. diff --git a/drivers/net/atlx/atl1.h b/drivers/net/atlx/atl1.h index 51893d6..a5015b1 100644 --- a/drivers/net/atlx/atl1.h +++ b/drivers/net/atlx/atl1.h @@ -1,7 +1,7 @@ /* * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. * Copyright(c) 2006 - 2007 Chris Snook - * Copyright(c) 2006 Jay Cliburn + * Copyright(c) 2006 - 2008 Jay Cliburn * * Derived from Intel e1000 driver * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c index f06b854..b3e7fcf 100644 --- a/drivers/net/atlx/atlx.c +++ b/drivers/net/atlx/atlx.c @@ -2,7 +2,7 @@ * * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. * Copyright(c) 2006 - 2007 Chris Snook - * Copyright(c) 2006 Jay Cliburn + * Copyright(c) 2006 - 2008 Jay Cliburn * Copyright(c) 2007 Atheros Corporation. All rights reserved. * * Derived from Intel e1000 driver diff --git a/drivers/net/atlx/atlx.h b/drivers/net/atlx/atlx.h index 9672188..297a03d 100644 --- a/drivers/net/atlx/atlx.h +++ b/drivers/net/atlx/atlx.h @@ -2,7 +2,7 @@ * * Copyright(c) 2005 - 2006 Attansic Corporation. All rights reserved. * Copyright(c) 2006 - 2007 Chris Snook - * Copyright(c) 2006 Jay Cliburn + * Copyright(c) 2006 - 2008 Jay Cliburn * Copyright(c) 2007 Atheros Corporation. All rights reserved. * * Derived from Intel e1000 driver @@ -29,7 +29,7 @@ #include #include -#define ATLX_DRIVER_VERSION "2.1.1" +#define ATLX_DRIVER_VERSION "2.1.3" MODULE_AUTHOR("Xiong Huang , \ Chris Snook , Jay Cliburn "); MODULE_LICENSE("GPL"); -- cgit v1.1 From 0f7229dde3f2b5373e26e7d7dd35012bd975e452 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 9 May 2008 02:16:19 +0200 Subject: myri10ge: update firmware headers Update myri10ge firmware headers. Signed-off-by: Brice Goglin Signed-off-by: Andrew Gallatin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge_mcp.h | 56 +++++++++++++++++++++++--- drivers/net/myri10ge/myri10ge_mcp_gen_header.h | 39 +++++++----------- 2 files changed, 64 insertions(+), 31 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge_mcp.h b/drivers/net/myri10ge/myri10ge_mcp.h index 58e5717..fdbeeee 100644 --- a/drivers/net/myri10ge/myri10ge_mcp.h +++ b/drivers/net/myri10ge/myri10ge_mcp.h @@ -10,7 +10,7 @@ struct mcp_dma_addr { __be32 low; }; -/* 4 Bytes. 8 Bytes for NDIS drivers. */ +/* 4 Bytes */ struct mcp_slot { __sum16 checksum; __be16 length; @@ -144,6 +144,7 @@ enum myri10ge_mcp_cmd_type { * a power of 2 number of entries. */ MXGEFW_CMD_SET_INTRQ_SIZE, /* in bytes */ +#define MXGEFW_CMD_SET_INTRQ_SIZE_FLAG_NO_STRICT_SIZE_CHECK (1 << 31) /* command to bring ethernet interface up. Above parameters * (plus mtu & mac address) must have been exchanged prior @@ -221,10 +222,14 @@ enum myri10ge_mcp_cmd_type { MXGEFW_CMD_GET_MAX_RSS_QUEUES, MXGEFW_CMD_ENABLE_RSS_QUEUES, /* data0 = number of slices n (0, 1, ..., n-1) to enable - * data1 = interrupt mode. 0=share one INTx/MSI, 1=use one MSI-X per queue. + * data1 = interrupt mode. + * 0=share one INTx/MSI, 1=use one MSI-X per queue. * If all queues share one interrupt, the driver must have set * RSS_SHARED_INTERRUPT_DMA before enabling queues. */ +#define MXGEFW_SLICE_INTR_MODE_SHARED 0 +#define MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE 1 + MXGEFW_CMD_GET_RSS_SHARED_INTERRUPT_MASK_OFFSET, MXGEFW_CMD_SET_RSS_SHARED_INTERRUPT_DMA, /* data0, data1 = bus address lsw, msw */ @@ -241,10 +246,14 @@ enum myri10ge_mcp_cmd_type { * 0: disable rss. nic does not distribute receive packets. * 1: enable rss. nic distributes receive packets among queues. * data1 = hash type - * 1: IPV4 - * 2: TCP_IPV4 - * 3: IPV4 | TCP_IPV4 + * 1: IPV4 (required by RSS) + * 2: TCP_IPV4 (required by RSS) + * 3: IPV4 | TCP_IPV4 (required by RSS) + * 4: source port */ +#define MXGEFW_RSS_HASH_TYPE_IPV4 0x1 +#define MXGEFW_RSS_HASH_TYPE_TCP_IPV4 0x2 +#define MXGEFW_RSS_HASH_TYPE_SRC_PORT 0x4 MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE, /* Return data = the max. size of the entire headers of a IPv6 TSO packet. @@ -260,6 +269,8 @@ enum myri10ge_mcp_cmd_type { * 0: Linux/FreeBSD style (NIC default) * 1: NDIS/NetBSD style */ +#define MXGEFW_TSO_MODE_LINUX 0 +#define MXGEFW_TSO_MODE_NDIS 1 MXGEFW_CMD_MDIO_READ, /* data0 = dev_addr (PMA/PMD or PCS ...), data1 = register/addr */ @@ -286,6 +297,38 @@ enum myri10ge_mcp_cmd_type { /* Return data = NIC memory offset of mcp_vpump_public_global */ MXGEFW_CMD_RESET_VPUMP, /* Resets the VPUMP state */ + + MXGEFW_CMD_SET_RSS_MCP_SLOT_TYPE, + /* data0 = mcp_slot type to use. + * 0 = the default 4B mcp_slot + * 1 = 8B mcp_slot_8 + */ +#define MXGEFW_RSS_MCP_SLOT_TYPE_MIN 0 +#define MXGEFW_RSS_MCP_SLOT_TYPE_WITH_HASH 1 + + MXGEFW_CMD_SET_THROTTLE_FACTOR, + /* set the throttle factor for ethp_z8e + * data0 = throttle_factor + * throttle_factor = 256 * pcie-raw-speed / tx_speed + * tx_speed = 256 * pcie-raw-speed / throttle_factor + * + * For PCI-E x8: pcie-raw-speed == 16Gb/s + * For PCI-E x4: pcie-raw-speed == 8Gb/s + * + * ex1: throttle_factor == 0x1a0 (416), tx_speed == 1.23GB/s == 9.846 Gb/s + * ex2: throttle_factor == 0x200 (512), tx_speed == 1.0GB/s == 8 Gb/s + * + * with tx_boundary == 2048, max-throttle-factor == 8191 => min-speed == 500Mb/s + * with tx_boundary == 4096, max-throttle-factor == 4095 => min-speed == 1Gb/s + */ + + MXGEFW_CMD_VPUMP_UP, + /* Allocates VPump Connection, Send Request and Zero copy buffer address tables */ + MXGEFW_CMD_GET_VPUMP_CLK, + /* Get the lanai clock */ + + MXGEFW_CMD_GET_DCA_OFFSET, + /* offset of dca control for WDMAs */ }; enum myri10ge_mcp_cmd_status { @@ -302,7 +345,8 @@ enum myri10ge_mcp_cmd_status { MXGEFW_CMD_ERROR_UNALIGNED, MXGEFW_CMD_ERROR_NO_MDIO, MXGEFW_CMD_ERROR_XFP_FAILURE, - MXGEFW_CMD_ERROR_XFP_ABSENT + MXGEFW_CMD_ERROR_XFP_ABSENT, + MXGEFW_CMD_ERROR_BAD_PCIE_LINK }; #define MXGEFW_OLD_IRQ_DATA_LEN 40 diff --git a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h index 16a810d..07d65c2 100644 --- a/drivers/net/myri10ge/myri10ge_mcp_gen_header.h +++ b/drivers/net/myri10ge/myri10ge_mcp_gen_header.h @@ -1,30 +1,6 @@ #ifndef __MYRI10GE_MCP_GEN_HEADER_H__ #define __MYRI10GE_MCP_GEN_HEADER_H__ -/* this file define a standard header used as a first entry point to - * exchange information between firmware/driver and driver. The - * header structure can be anywhere in the mcp. It will usually be in - * the .data section, because some fields needs to be initialized at - * compile time. - * The 32bit word at offset MX_HEADER_PTR_OFFSET in the mcp must - * contains the location of the header. - * - * Typically a MCP will start with the following: - * .text - * .space 52 ! to help catch MEMORY_INT errors - * bt start ! jump to real code - * nop - * .long _gen_mcp_header - * - * The source will have a definition like: - * - * mcp_gen_header_t gen_mcp_header = { - * .header_length = sizeof(mcp_gen_header_t), - * .mcp_type = MCP_TYPE_XXX, - * .version = "something $Id: mcp_gen_header.h,v 1.2 2006/05/13 10:04:35 bgoglin Exp $", - * .mcp_globals = (unsigned)&Globals - * }; - */ #define MCP_HEADER_PTR_OFFSET 0x3c @@ -32,13 +8,14 @@ #define MCP_TYPE_PCIE 0x70636965 /* "PCIE" pcie-only MCP */ #define MCP_TYPE_ETH 0x45544820 /* "ETH " */ #define MCP_TYPE_MCP0 0x4d435030 /* "MCP0" */ +#define MCP_TYPE_DFLT 0x20202020 /* " " */ struct mcp_gen_header { /* the first 4 fields are filled at compile time */ unsigned header_length; __be32 mcp_type; char version[128]; - unsigned mcp_globals; /* pointer to mcp-type specific structure */ + unsigned mcp_private; /* pointer to mcp-type specific structure */ /* filled by the MCP at run-time */ unsigned sram_size; @@ -53,6 +30,18 @@ struct mcp_gen_header { * * Never remove any field. Keep everything naturally align. */ + + /* Specifies if the running mcp is mcp0, 1, or 2. */ + unsigned char mcp_index; + unsigned char disable_rabbit; + unsigned char unaligned_tlp; + unsigned char pad1; + unsigned counters_addr; + unsigned copy_block_info; /* for small mcps loaded with "lload -d" */ + unsigned short handoff_id_major; /* must be equal */ + unsigned short handoff_id_caps; /* bitfield: new mcp must have superset */ + unsigned msix_table_addr; /* start address of msix table in firmware */ + /* 8 */ }; #endif /* __MYRI10GE_MCP_GEN_HEADER_H__ */ -- cgit v1.1 From d1ce3a0f1a07b48e16ebbc71886086779b52f630 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 9 May 2008 02:16:53 +0200 Subject: myri10ge: fix module parameter descriptions Remove useless linebreaks at the end of MODULE_PARM_DESC and fix the description of myri10ge_lro_max_pkts. Signed-off-by: Brice Goglin Signed-off-by: Andrew Gallatin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index ef63c8d..162c624 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -228,58 +228,58 @@ static char *myri10ge_fw_aligned = "myri10ge_eth_z8e.dat"; static char *myri10ge_fw_name = NULL; module_param(myri10ge_fw_name, charp, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name\n"); +MODULE_PARM_DESC(myri10ge_fw_name, "Firmware image name"); static int myri10ge_ecrc_enable = 1; module_param(myri10ge_ecrc_enable, int, S_IRUGO); -MODULE_PARM_DESC(myri10ge_ecrc_enable, "Enable Extended CRC on PCI-E\n"); +MODULE_PARM_DESC(myri10ge_ecrc_enable, "Enable Extended CRC on PCI-E"); static int myri10ge_max_intr_slots = 1024; module_param(myri10ge_max_intr_slots, int, S_IRUGO); -MODULE_PARM_DESC(myri10ge_max_intr_slots, "Interrupt queue slots\n"); +MODULE_PARM_DESC(myri10ge_max_intr_slots, "Interrupt queue slots"); static int myri10ge_small_bytes = -1; /* -1 == auto */ module_param(myri10ge_small_bytes, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(myri10ge_small_bytes, "Threshold of small packets\n"); +MODULE_PARM_DESC(myri10ge_small_bytes, "Threshold of small packets"); static int myri10ge_msi = 1; /* enable msi by default */ module_param(myri10ge_msi, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(myri10ge_msi, "Enable Message Signalled Interrupts\n"); +MODULE_PARM_DESC(myri10ge_msi, "Enable Message Signalled Interrupts"); static int myri10ge_intr_coal_delay = 75; module_param(myri10ge_intr_coal_delay, int, S_IRUGO); -MODULE_PARM_DESC(myri10ge_intr_coal_delay, "Interrupt coalescing delay\n"); +MODULE_PARM_DESC(myri10ge_intr_coal_delay, "Interrupt coalescing delay"); static int myri10ge_flow_control = 1; module_param(myri10ge_flow_control, int, S_IRUGO); -MODULE_PARM_DESC(myri10ge_flow_control, "Pause parameter\n"); +MODULE_PARM_DESC(myri10ge_flow_control, "Pause parameter"); static int myri10ge_deassert_wait = 1; module_param(myri10ge_deassert_wait, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(myri10ge_deassert_wait, - "Wait when deasserting legacy interrupts\n"); + "Wait when deasserting legacy interrupts"); static int myri10ge_force_firmware = 0; module_param(myri10ge_force_firmware, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_force_firmware, - "Force firmware to assume aligned completions\n"); + "Force firmware to assume aligned completions"); static int myri10ge_initial_mtu = MYRI10GE_MAX_ETHER_MTU - ETH_HLEN; module_param(myri10ge_initial_mtu, int, S_IRUGO); -MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU\n"); +MODULE_PARM_DESC(myri10ge_initial_mtu, "Initial MTU"); static int myri10ge_napi_weight = 64; module_param(myri10ge_napi_weight, int, S_IRUGO); -MODULE_PARM_DESC(myri10ge_napi_weight, "Set NAPI weight\n"); +MODULE_PARM_DESC(myri10ge_napi_weight, "Set NAPI weight"); static int myri10ge_watchdog_timeout = 1; module_param(myri10ge_watchdog_timeout, int, S_IRUGO); -MODULE_PARM_DESC(myri10ge_watchdog_timeout, "Set watchdog timeout\n"); +MODULE_PARM_DESC(myri10ge_watchdog_timeout, "Set watchdog timeout"); static int myri10ge_max_irq_loops = 1048576; module_param(myri10ge_max_irq_loops, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_max_irq_loops, - "Set stuck legacy IRQ detection threshold\n"); + "Set stuck legacy IRQ detection threshold"); #define MYRI10GE_MSG_DEFAULT NETIF_MSG_LINK @@ -289,21 +289,22 @@ MODULE_PARM_DESC(myri10ge_debug, "Debug level (0=none,...,16=all)"); static int myri10ge_lro = 1; module_param(myri10ge_lro, int, S_IRUGO); -MODULE_PARM_DESC(myri10ge_lro, "Enable large receive offload\n"); +MODULE_PARM_DESC(myri10ge_lro, "Enable large receive offload"); static int myri10ge_lro_max_pkts = MYRI10GE_LRO_MAX_PKTS; module_param(myri10ge_lro_max_pkts, int, S_IRUGO); -MODULE_PARM_DESC(myri10ge_lro, "Number of LRO packets to be aggregated\n"); +MODULE_PARM_DESC(myri10ge_lro_max_pkts, + "Number of LRO packets to be aggregated"); static int myri10ge_fill_thresh = 256; module_param(myri10ge_fill_thresh, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed\n"); +MODULE_PARM_DESC(myri10ge_fill_thresh, "Number of empty rx slots allowed"); static int myri10ge_reset_recover = 1; static int myri10ge_wcfifo = 0; module_param(myri10ge_wcfifo, int, S_IRUGO); -MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled\n"); +MODULE_PARM_DESC(myri10ge_wcfifo, "Enable WC Fifo when WC is enabled"); #define MYRI10GE_FW_OFFSET 1024*1024 #define MYRI10GE_HIGHPART_TO_U32(X) \ -- cgit v1.1 From d93ca2a453f8e5734359267866ab4f3341aa8749 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 9 May 2008 02:17:16 +0200 Subject: myri10ge: increase and fix handoff timeout Increase the handoff timeout to 512ms so as to give the aeluros based NICs sufficient time to handoff without relying on the msleep() being sloppy, and accidentally sleeping way longer than the 20ms we specified in 20 separate 1ms sleeps. Fix typo in the handoff sleep delay, which made it additive, not exponential. Signed-off-by: Brice Goglin Signed-off-by: Andrew Gallatin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 162c624..ad6c619 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -682,8 +682,8 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) msleep(1); mb(); i = 0; - while (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 20) { - msleep(1); + while (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA && i < 9) { + msleep(1 << i); i++; } if (mgp->cmd->data != MYRI10GE_NO_CONFIRM_DATA) { -- cgit v1.1 From f8fd57c11159d89d0d9cd624eafad41c680e8f6e Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 9 May 2008 02:17:37 +0200 Subject: myri10ge: properly align scratch buffers Properly align scratch buffers when making boot commands. Signed-off-by: Brice Goglin Signed-off-by: Andrew Gallatin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index ad6c619..3f871c4 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -443,7 +443,7 @@ abort: static void myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable) { char __iomem *submit; - __be32 buf[16]; + __be32 buf[16] __attribute__ ((__aligned__(8))); u32 dma_low, dma_high; int i; @@ -613,7 +613,7 @@ static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp) static int myri10ge_load_firmware(struct myri10ge_priv *mgp) { char __iomem *submit; - __be32 buf[16]; + __be32 buf[16] __attribute__ ((__aligned__(8))); u32 dma_low, dma_high, size; int status, i; struct myri10ge_cmd cmd; -- cgit v1.1 From c0bf8801535d45df3597839edf864e24f60a4188 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 9 May 2008 02:18:24 +0200 Subject: myri10ge: report FIBER in ethtool for XFP based NIC Make ethtool report FIBER for XFP based NIC's port type. Don't bother to poke around and try to find out what is in the XFP cage, since Linux does not have separate media types for -SR -LR, etc. Signed-off-by: Brice Goglin Signed-off-by: Andrew Gallatin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 3f871c4..4a65e41 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -205,6 +205,7 @@ struct myri10ge_priv { int pause; char *fw_name; char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE]; + char *product_code_string; char fw_version[128]; int fw_ver_major; int fw_ver_minor; @@ -421,6 +422,10 @@ static int myri10ge_read_mac_addr(struct myri10ge_priv *mgp) ptr += 1; } } + if (memcmp(ptr, "PC=", 3) == 0) { + ptr += 3; + mgp->product_code_string = ptr; + } if (memcmp((const void *)ptr, "SN=", 3) == 0) { ptr += 3; mgp->serial_number = simple_strtoul(ptr, &ptr, 10); @@ -1304,9 +1309,39 @@ static irqreturn_t myri10ge_intr(int irq, void *arg) static int myri10ge_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) { + struct myri10ge_priv *mgp = netdev_priv(netdev); + char *ptr; + int i; + cmd->autoneg = AUTONEG_DISABLE; cmd->speed = SPEED_10000; cmd->duplex = DUPLEX_FULL; + + /* + * parse the product code to deterimine the interface type + * (CX4, XFP, Quad Ribbon Fiber) by looking at the character + * after the 3rd dash in the driver's cached copy of the + * EEPROM's product code string. + */ + ptr = mgp->product_code_string; + if (ptr == NULL) { + printk(KERN_ERR "myri10ge: %s: Missing product code\n", + netdev->name); + return 0; + } + for (i = 0; i < 3; i++, ptr++) { + ptr = strchr(ptr, '-'); + if (ptr == NULL) { + printk(KERN_ERR "myri10ge: %s: Invalid product " + "code %s\n", netdev->name, + mgp->product_code_string); + return 0; + } + } + if (*ptr == 'R' || *ptr == 'Q') { + /* We've found either an XFP or quad ribbon fiber */ + cmd->port = PORT_FIBRE; + } return 0; } -- cgit v1.1 From bd2db0cf2411ebc081d45bde1b7c6cf726b832f2 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 9 May 2008 02:18:45 +0200 Subject: myri10ge: add barrier in myri10ge_send_cmd Add a barrier() in the usleep() loop in myri10ge_send_cmd(). Without the barrier, some mips machine never notices that the firmware has DMA'ed the response. Signed-off-by: Brice Goglin Signed-off-by: Andrew Gallatin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 4a65e41..48fe624 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -361,8 +361,10 @@ myri10ge_send_cmd(struct myri10ge_priv *mgp, u32 cmd, for (sleep_total = 0; sleep_total < 1000 && response->result == htonl(MYRI10GE_NO_RESPONSE_RESULT); - sleep_total += 10) + sleep_total += 10) { udelay(10); + mb(); + } } else { /* use msleep for most command */ for (sleep_total = 0; -- cgit v1.1 From 99f5f87eb689c5766fa2c101fe75310a7f9ba3cd Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 9 May 2008 02:19:08 +0200 Subject: myri10ge: trivial formatting fix Add some blank lines to uniformize the code and match the upstream code. Signed-off-by: Brice Goglin Signed-off-by: Andrew Gallatin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 48fe624..9165a55 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -1328,7 +1328,7 @@ myri10ge_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd) ptr = mgp->product_code_string; if (ptr == NULL) { printk(KERN_ERR "myri10ge: %s: Missing product code\n", - netdev->name); + netdev->name); return 0; } for (i = 0; i < 3; i++, ptr++) { @@ -1362,6 +1362,7 @@ static int myri10ge_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coal) { struct myri10ge_priv *mgp = netdev_priv(netdev); + coal->rx_coalesce_usecs = mgp->intr_coal_delay; return 0; } @@ -1421,6 +1422,7 @@ myri10ge_get_ringparam(struct net_device *netdev, static u32 myri10ge_get_rx_csum(struct net_device *netdev) { struct myri10ge_priv *mgp = netdev_priv(netdev); + if (mgp->csum_flag) return 1; else @@ -1430,6 +1432,7 @@ static u32 myri10ge_get_rx_csum(struct net_device *netdev) static int myri10ge_set_rx_csum(struct net_device *netdev, u32 csum_enabled) { struct myri10ge_priv *mgp = netdev_priv(netdev); + if (csum_enabled) mgp->csum_flag = MXGEFW_FLAGS_CKSUM; else -- cgit v1.1 From eca3fd83436853483837f010d9c3fefafa46a15c Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 9 May 2008 02:19:29 +0200 Subject: myri10ge: fix potential infinite loop in enable_ecrc Fix another potential for an infinite loop while looking for the root port in myri10ge_enable_ecrc(). Signed-off-by: Brice Goglin Signed-off-by: Andrew Gallatin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 9165a55..6526214 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -2657,13 +2657,14 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) ext_type = (val & PCI_EXP_FLAGS_TYPE) >> 4; if (ext_type != PCI_EXP_TYPE_ROOT_PORT) { if (myri10ge_ecrc_enable > 1) { - struct pci_dev *old_bridge = bridge; + struct pci_dev *prev_bridge, *old_bridge = bridge; /* Walk the hierarchy up to the root port * where ECRC has to be enabled */ do { + prev_bridge = bridge; bridge = bridge->bus->self; - if (!bridge) { + if (!bridge || prev_bridge == bridge) { dev_err(dev, "Failed to find root port" " to force ECRC\n"); -- cgit v1.1 From b53bef84c27e68efac9b608392acd1fc14cb6ce7 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 9 May 2008 02:20:03 +0200 Subject: myri10ge: move data structures into a single slice To prepare and simplify multislice rx support, add a single slice structure and move some fields in there. No functional change yet. Signed-off-by: Brice Goglin Signed-off-by: Andrew Gallatin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 594 +++++++++++++++++++++------------------- 1 file changed, 316 insertions(+), 278 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 6526214..5edcbfe 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -144,11 +144,13 @@ struct myri10ge_tx_buf { char *req_bytes; struct myri10ge_tx_buffer_state *info; int mask; /* number of transmit slots -1 */ - int boundary; /* boundary transmits cannot cross */ int req ____cacheline_aligned; /* transmit slots submitted */ int pkt_start; /* packets started */ + int stop_queue; + int linearized; int done ____cacheline_aligned; /* transmit slots completed */ int pkt_done; /* packets completed */ + int wake_queue; }; struct myri10ge_rx_done { @@ -160,29 +162,49 @@ struct myri10ge_rx_done { struct net_lro_desc lro_desc[MYRI10GE_MAX_LRO_DESCRIPTORS]; }; -struct myri10ge_priv { - int running; /* running? */ - int csum_flag; /* rx_csums? */ +struct myri10ge_slice_netstats { + unsigned long rx_packets; + unsigned long tx_packets; + unsigned long rx_bytes; + unsigned long tx_bytes; + unsigned long rx_dropped; + unsigned long tx_dropped; +}; + +struct myri10ge_slice_state { struct myri10ge_tx_buf tx; /* transmit ring */ struct myri10ge_rx_buf rx_small; struct myri10ge_rx_buf rx_big; struct myri10ge_rx_done rx_done; + struct net_device *dev; + struct napi_struct napi; + struct myri10ge_priv *mgp; + struct myri10ge_slice_netstats stats; + __be32 __iomem *irq_claim; + struct mcp_irq_data *fw_stats; + dma_addr_t fw_stats_bus; + int watchdog_tx_done; + int watchdog_tx_req; +}; + +struct myri10ge_priv { + struct myri10ge_slice_state ss; + int tx_boundary; /* boundary transmits cannot cross */ + int running; /* running? */ + int csum_flag; /* rx_csums? */ int small_bytes; int big_bytes; struct net_device *dev; - struct napi_struct napi; struct net_device_stats stats; + spinlock_t stats_lock; u8 __iomem *sram; int sram_size; unsigned long board_span; unsigned long iomem_base; - __be32 __iomem *irq_claim; __be32 __iomem *irq_deassert; char *mac_addr_string; struct mcp_cmd_response *cmd; dma_addr_t cmd_bus; - struct mcp_irq_data *fw_stats; - dma_addr_t fw_stats_bus; struct pci_dev *pdev; int msi_enabled; u32 link_state; @@ -191,17 +213,12 @@ struct myri10ge_priv { __be32 __iomem *intr_coal_delay_ptr; int mtrr; int wc_enabled; - int wake_queue; - int stop_queue; int down_cnt; wait_queue_head_t down_wq; struct work_struct watchdog_work; struct timer_list watchdog_timer; - int watchdog_tx_done; - int watchdog_tx_req; - int watchdog_pause; int watchdog_resets; - int tx_linearized; + int watchdog_pause; int pause; char *fw_name; char eeprom_strings[MYRI10GE_EEPROM_STRINGS_SIZE]; @@ -643,7 +660,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) } dev_info(&mgp->pdev->dev, "Successfully adopted running firmware\n"); - if (mgp->tx.boundary == 4096) { + if (mgp->tx_boundary == 4096) { dev_warn(&mgp->pdev->dev, "Using firmware currently running on NIC" ". For optimal\n"); @@ -654,7 +671,7 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) } mgp->fw_name = "adopted"; - mgp->tx.boundary = 2048; + mgp->tx_boundary = 2048; return status; } @@ -780,7 +797,7 @@ static int myri10ge_dma_test(struct myri10ge_priv *mgp, int test_type) * transfers took to complete. */ - len = mgp->tx.boundary; + len = mgp->tx_boundary; cmd.data0 = MYRI10GE_LOWPART_TO_U32(dmatest_bus); cmd.data1 = MYRI10GE_HIGHPART_TO_U32(dmatest_bus); @@ -842,17 +859,17 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) /* Now exchange information about interrupts */ - bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry); - memset(mgp->rx_done.entry, 0, bytes); + bytes = myri10ge_max_intr_slots * sizeof(*mgp->ss.rx_done.entry); + memset(mgp->ss.rx_done.entry, 0, bytes); cmd.data0 = (u32) bytes; status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd, 0); - cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->rx_done.bus); - cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->rx_done.bus); + cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->ss.rx_done.bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->ss.rx_done.bus); status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA, &cmd, 0); status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd, 0); - mgp->irq_claim = (__iomem __be32 *) (mgp->sram + cmd.data0); + mgp->ss.irq_claim = (__iomem __be32 *) (mgp->sram + cmd.data0); status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd, 0); mgp->irq_deassert = (__iomem __be32 *) (mgp->sram + cmd.data0); @@ -866,17 +883,17 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) } put_be32(htonl(mgp->intr_coal_delay), mgp->intr_coal_delay_ptr); - memset(mgp->rx_done.entry, 0, bytes); + memset(mgp->ss.rx_done.entry, 0, bytes); /* reset mcp/driver shared state back to 0 */ - mgp->tx.req = 0; - mgp->tx.done = 0; - mgp->tx.pkt_start = 0; - mgp->tx.pkt_done = 0; - mgp->rx_big.cnt = 0; - mgp->rx_small.cnt = 0; - mgp->rx_done.idx = 0; - mgp->rx_done.cnt = 0; + mgp->ss.tx.req = 0; + mgp->ss.tx.done = 0; + mgp->ss.tx.pkt_start = 0; + mgp->ss.tx.pkt_done = 0; + mgp->ss.rx_big.cnt = 0; + mgp->ss.rx_small.cnt = 0; + mgp->ss.rx_done.idx = 0; + mgp->ss.rx_done.cnt = 0; mgp->link_changes = 0; status = myri10ge_update_mac_address(mgp, mgp->dev->dev_addr); myri10ge_change_pause(mgp, mgp->pause); @@ -1028,9 +1045,10 @@ myri10ge_unmap_rx_page(struct pci_dev *pdev, * page into an skb */ static inline int -myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, +myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx, int bytes, int len, __wsum csum) { + struct myri10ge_priv *mgp = ss->mgp; struct sk_buff *skb; struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME]; int i, idx, hlen, remainder; @@ -1060,11 +1078,10 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, rx_frags[0].page_offset += MXGEFW_PAD; rx_frags[0].size -= MXGEFW_PAD; len -= MXGEFW_PAD; - lro_receive_frags(&mgp->rx_done.lro_mgr, rx_frags, + lro_receive_frags(&ss->rx_done.lro_mgr, rx_frags, len, len, - /* opaque, will come back in get_frag_header */ - (void *)(__force unsigned long)csum, - csum); + /* opaque, will come back in get_frag_header */ + (void *)(__force unsigned long)csum, csum); return 1; } @@ -1104,10 +1121,11 @@ myri10ge_rx_done(struct myri10ge_priv *mgp, struct myri10ge_rx_buf *rx, return 1; } -static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index) +static inline void +myri10ge_tx_done(struct myri10ge_slice_state *ss, int mcp_index) { - struct pci_dev *pdev = mgp->pdev; - struct myri10ge_tx_buf *tx = &mgp->tx; + struct pci_dev *pdev = ss->mgp->pdev; + struct myri10ge_tx_buf *tx = &ss->tx; struct sk_buff *skb; int idx, len; @@ -1125,8 +1143,8 @@ static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index) len = pci_unmap_len(&tx->info[idx], len); pci_unmap_len_set(&tx->info[idx], len, 0); if (skb) { - mgp->stats.tx_bytes += skb->len; - mgp->stats.tx_packets++; + ss->stats.tx_bytes += skb->len; + ss->stats.tx_packets++; dev_kfree_skb_irq(skb); if (len) pci_unmap_single(pdev, @@ -1142,16 +1160,18 @@ static inline void myri10ge_tx_done(struct myri10ge_priv *mgp, int mcp_index) } } /* start the queue if we've stopped it */ - if (netif_queue_stopped(mgp->dev) + if (netif_queue_stopped(ss->dev) && tx->req - tx->done < (tx->mask >> 1)) { - mgp->wake_queue++; - netif_wake_queue(mgp->dev); + tx->wake_queue++; + netif_wake_queue(ss->dev); } } -static inline int myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int budget) +static inline int +myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) { - struct myri10ge_rx_done *rx_done = &mgp->rx_done; + struct myri10ge_rx_done *rx_done = &ss->rx_done; + struct myri10ge_priv *mgp = ss->mgp; unsigned long rx_bytes = 0; unsigned long rx_packets = 0; unsigned long rx_ok; @@ -1167,11 +1187,11 @@ static inline int myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int budget) rx_done->entry[idx].length = 0; checksum = csum_unfold(rx_done->entry[idx].checksum); if (length <= mgp->small_bytes) - rx_ok = myri10ge_rx_done(mgp, &mgp->rx_small, + rx_ok = myri10ge_rx_done(ss, &ss->rx_small, mgp->small_bytes, length, checksum); else - rx_ok = myri10ge_rx_done(mgp, &mgp->rx_big, + rx_ok = myri10ge_rx_done(ss, &ss->rx_big, mgp->big_bytes, length, checksum); rx_packets += rx_ok; @@ -1182,25 +1202,25 @@ static inline int myri10ge_clean_rx_done(struct myri10ge_priv *mgp, int budget) } rx_done->idx = idx; rx_done->cnt = cnt; - mgp->stats.rx_packets += rx_packets; - mgp->stats.rx_bytes += rx_bytes; + ss->stats.rx_packets += rx_packets; + ss->stats.rx_bytes += rx_bytes; if (myri10ge_lro) lro_flush_all(&rx_done->lro_mgr); /* restock receive rings if needed */ - if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt < myri10ge_fill_thresh) - myri10ge_alloc_rx_pages(mgp, &mgp->rx_small, + if (ss->rx_small.fill_cnt - ss->rx_small.cnt < myri10ge_fill_thresh) + myri10ge_alloc_rx_pages(mgp, &ss->rx_small, mgp->small_bytes + MXGEFW_PAD, 0); - if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt < myri10ge_fill_thresh) - myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0); + if (ss->rx_big.fill_cnt - ss->rx_big.cnt < myri10ge_fill_thresh) + myri10ge_alloc_rx_pages(mgp, &ss->rx_big, mgp->big_bytes, 0); return work_done; } static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) { - struct mcp_irq_data *stats = mgp->fw_stats; + struct mcp_irq_data *stats = mgp->ss.fw_stats; if (unlikely(stats->stats_updated)) { unsigned link_up = ntohl(stats->link_up); @@ -1227,9 +1247,9 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) } } if (mgp->rdma_tags_available != - ntohl(mgp->fw_stats->rdma_tags_available)) { + ntohl(stats->rdma_tags_available)) { mgp->rdma_tags_available = - ntohl(mgp->fw_stats->rdma_tags_available); + ntohl(stats->rdma_tags_available); printk(KERN_WARNING "myri10ge: %s: RDMA timed out! " "%d tags left\n", mgp->dev->name, mgp->rdma_tags_available); @@ -1242,26 +1262,27 @@ static inline void myri10ge_check_statblock(struct myri10ge_priv *mgp) static int myri10ge_poll(struct napi_struct *napi, int budget) { - struct myri10ge_priv *mgp = - container_of(napi, struct myri10ge_priv, napi); - struct net_device *netdev = mgp->dev; + struct myri10ge_slice_state *ss = + container_of(napi, struct myri10ge_slice_state, napi); + struct net_device *netdev = ss->mgp->dev; int work_done; /* process as many rx events as NAPI will allow */ - work_done = myri10ge_clean_rx_done(mgp, budget); + work_done = myri10ge_clean_rx_done(ss, budget); if (work_done < budget) { netif_rx_complete(netdev, napi); - put_be32(htonl(3), mgp->irq_claim); + put_be32(htonl(3), ss->irq_claim); } return work_done; } static irqreturn_t myri10ge_intr(int irq, void *arg) { - struct myri10ge_priv *mgp = arg; - struct mcp_irq_data *stats = mgp->fw_stats; - struct myri10ge_tx_buf *tx = &mgp->tx; + struct myri10ge_slice_state *ss = arg; + struct myri10ge_priv *mgp = ss->mgp; + struct mcp_irq_data *stats = ss->fw_stats; + struct myri10ge_tx_buf *tx = &ss->tx; u32 send_done_count; int i; @@ -1272,7 +1293,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg) /* low bit indicates receives are present, so schedule * napi poll handler */ if (stats->valid & 1) - netif_rx_schedule(mgp->dev, &mgp->napi); + netif_rx_schedule(ss->dev, &ss->napi); if (!mgp->msi_enabled) { put_be32(0, mgp->irq_deassert); @@ -1289,7 +1310,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg) /* check for transmit completes and receives */ send_done_count = ntohl(stats->send_done_count); if (send_done_count != tx->pkt_done) - myri10ge_tx_done(mgp, (int)send_done_count); + myri10ge_tx_done(ss, (int)send_done_count); if (unlikely(i > myri10ge_max_irq_loops)) { printk(KERN_WARNING "myri10ge: %s: irq stuck?\n", mgp->dev->name); @@ -1304,7 +1325,7 @@ static irqreturn_t myri10ge_intr(int irq, void *arg) myri10ge_check_statblock(mgp); - put_be32(htonl(3), mgp->irq_claim + 1); + put_be32(htonl(3), ss->irq_claim + 1); return (IRQ_HANDLED); } @@ -1409,10 +1430,10 @@ myri10ge_get_ringparam(struct net_device *netdev, { struct myri10ge_priv *mgp = netdev_priv(netdev); - ring->rx_mini_max_pending = mgp->rx_small.mask + 1; - ring->rx_max_pending = mgp->rx_big.mask + 1; + ring->rx_mini_max_pending = mgp->ss.rx_small.mask + 1; + ring->rx_max_pending = mgp->ss.rx_big.mask + 1; ring->rx_jumbo_max_pending = 0; - ring->tx_max_pending = mgp->rx_small.mask + 1; + ring->tx_max_pending = mgp->ss.rx_small.mask + 1; ring->rx_mini_pending = ring->rx_mini_max_pending; ring->rx_pending = ring->rx_max_pending; ring->rx_jumbo_pending = ring->rx_jumbo_max_pending; @@ -1452,7 +1473,7 @@ static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled) return 0; } -static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = { +static const char myri10ge_gstrings_main_stats[][ETH_GSTRING_LEN] = { "rx_packets", "tx_packets", "rx_bytes", "tx_bytes", "rx_errors", "tx_errors", "rx_dropped", "tx_dropped", "multicast", "collisions", "rx_length_errors", "rx_over_errors", "rx_crc_errors", @@ -1462,28 +1483,39 @@ static const char myri10ge_gstrings_stats[][ETH_GSTRING_LEN] = { /* device-specific stats */ "tx_boundary", "WC", "irq", "MSI", "read_dma_bw_MBs", "write_dma_bw_MBs", "read_write_dma_bw_MBs", - "serial_number", "tx_pkt_start", "tx_pkt_done", - "tx_req", "tx_done", "rx_small_cnt", "rx_big_cnt", - "wake_queue", "stop_queue", "watchdog_resets", "tx_linearized", + "serial_number", "watchdog_resets", "link_changes", "link_up", "dropped_link_overflow", "dropped_link_error_or_filtered", "dropped_pause", "dropped_bad_phy", "dropped_bad_crc32", "dropped_unicast_filtered", "dropped_multicast_filtered", "dropped_runt", "dropped_overrun", "dropped_no_small_buffer", - "dropped_no_big_buffer", "LRO aggregated", "LRO flushed", + "dropped_no_big_buffer" +}; + +static const char myri10ge_gstrings_slice_stats[][ETH_GSTRING_LEN] = { + "----------- slice ---------", + "tx_pkt_start", "tx_pkt_done", "tx_req", "tx_done", + "rx_small_cnt", "rx_big_cnt", + "wake_queue", "stop_queue", "tx_linearized", "LRO aggregated", + "LRO flushed", "LRO avg aggr", "LRO no_desc" }; #define MYRI10GE_NET_STATS_LEN 21 -#define MYRI10GE_STATS_LEN ARRAY_SIZE(myri10ge_gstrings_stats) +#define MYRI10GE_MAIN_STATS_LEN ARRAY_SIZE(myri10ge_gstrings_main_stats) +#define MYRI10GE_SLICE_STATS_LEN ARRAY_SIZE(myri10ge_gstrings_slice_stats) static void myri10ge_get_strings(struct net_device *netdev, u32 stringset, u8 * data) { switch (stringset) { case ETH_SS_STATS: - memcpy(data, *myri10ge_gstrings_stats, - sizeof(myri10ge_gstrings_stats)); + memcpy(data, *myri10ge_gstrings_main_stats, + sizeof(myri10ge_gstrings_main_stats)); + data += sizeof(myri10ge_gstrings_main_stats); + memcpy(data, *myri10ge_gstrings_slice_stats, + sizeof(myri10ge_gstrings_slice_stats)); + data += sizeof(myri10ge_gstrings_slice_stats); break; } } @@ -1492,7 +1524,7 @@ static int myri10ge_get_sset_count(struct net_device *netdev, int sset) { switch (sset) { case ETH_SS_STATS: - return MYRI10GE_STATS_LEN; + return MYRI10GE_MAIN_STATS_LEN + MYRI10GE_SLICE_STATS_LEN; default: return -EOPNOTSUPP; } @@ -1503,12 +1535,13 @@ myri10ge_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 * data) { struct myri10ge_priv *mgp = netdev_priv(netdev); + struct myri10ge_slice_state *ss; int i; for (i = 0; i < MYRI10GE_NET_STATS_LEN; i++) data[i] = ((unsigned long *)&mgp->stats)[i]; - data[i++] = (unsigned int)mgp->tx.boundary; + data[i++] = (unsigned int)mgp->tx_boundary; data[i++] = (unsigned int)mgp->wc_enabled; data[i++] = (unsigned int)mgp->pdev->irq; data[i++] = (unsigned int)mgp->msi_enabled; @@ -1516,40 +1549,44 @@ myri10ge_get_ethtool_stats(struct net_device *netdev, data[i++] = (unsigned int)mgp->write_dma; data[i++] = (unsigned int)mgp->read_write_dma; data[i++] = (unsigned int)mgp->serial_number; - data[i++] = (unsigned int)mgp->tx.pkt_start; - data[i++] = (unsigned int)mgp->tx.pkt_done; - data[i++] = (unsigned int)mgp->tx.req; - data[i++] = (unsigned int)mgp->tx.done; - data[i++] = (unsigned int)mgp->rx_small.cnt; - data[i++] = (unsigned int)mgp->rx_big.cnt; - data[i++] = (unsigned int)mgp->wake_queue; - data[i++] = (unsigned int)mgp->stop_queue; data[i++] = (unsigned int)mgp->watchdog_resets; - data[i++] = (unsigned int)mgp->tx_linearized; data[i++] = (unsigned int)mgp->link_changes; - data[i++] = (unsigned int)ntohl(mgp->fw_stats->link_up); - data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_link_overflow); - data[i++] = - (unsigned int)ntohl(mgp->fw_stats->dropped_link_error_or_filtered); - data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_pause); - data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_bad_phy); - data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_bad_crc32); + + /* firmware stats are useful only in the first slice */ + ss = &mgp->ss; + data[i++] = (unsigned int)ntohl(ss->fw_stats->link_up); + data[i++] = (unsigned int)ntohl(ss->fw_stats->dropped_link_overflow); data[i++] = - (unsigned int)ntohl(mgp->fw_stats->dropped_unicast_filtered); + (unsigned int)ntohl(ss->fw_stats->dropped_link_error_or_filtered); + data[i++] = (unsigned int)ntohl(ss->fw_stats->dropped_pause); + data[i++] = (unsigned int)ntohl(ss->fw_stats->dropped_bad_phy); + data[i++] = (unsigned int)ntohl(ss->fw_stats->dropped_bad_crc32); + data[i++] = (unsigned int)ntohl(ss->fw_stats->dropped_unicast_filtered); data[i++] = - (unsigned int)ntohl(mgp->fw_stats->dropped_multicast_filtered); - data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_runt); - data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_overrun); - data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_small_buffer); - data[i++] = (unsigned int)ntohl(mgp->fw_stats->dropped_no_big_buffer); - data[i++] = mgp->rx_done.lro_mgr.stats.aggregated; - data[i++] = mgp->rx_done.lro_mgr.stats.flushed; - if (mgp->rx_done.lro_mgr.stats.flushed) - data[i++] = mgp->rx_done.lro_mgr.stats.aggregated / - mgp->rx_done.lro_mgr.stats.flushed; + (unsigned int)ntohl(ss->fw_stats->dropped_multicast_filtered); + data[i++] = (unsigned int)ntohl(ss->fw_stats->dropped_runt); + data[i++] = (unsigned int)ntohl(ss->fw_stats->dropped_overrun); + data[i++] = (unsigned int)ntohl(ss->fw_stats->dropped_no_small_buffer); + data[i++] = (unsigned int)ntohl(ss->fw_stats->dropped_no_big_buffer); + + data[i++] = 0; + data[i++] = (unsigned int)ss->tx.pkt_start; + data[i++] = (unsigned int)ss->tx.pkt_done; + data[i++] = (unsigned int)ss->tx.req; + data[i++] = (unsigned int)ss->tx.done; + data[i++] = (unsigned int)ss->rx_small.cnt; + data[i++] = (unsigned int)ss->rx_big.cnt; + data[i++] = (unsigned int)ss->tx.wake_queue; + data[i++] = (unsigned int)ss->tx.stop_queue; + data[i++] = (unsigned int)ss->tx.linearized; + data[i++] = ss->rx_done.lro_mgr.stats.aggregated; + data[i++] = ss->rx_done.lro_mgr.stats.flushed; + if (ss->rx_done.lro_mgr.stats.flushed) + data[i++] = ss->rx_done.lro_mgr.stats.aggregated / + ss->rx_done.lro_mgr.stats.flushed; else data[i++] = 0; - data[i++] = mgp->rx_done.lro_mgr.stats.no_desc; + data[i++] = ss->rx_done.lro_mgr.stats.no_desc; } static void myri10ge_set_msglevel(struct net_device *netdev, u32 value) @@ -1585,19 +1622,17 @@ static const struct ethtool_ops myri10ge_ethtool_ops = { .get_msglevel = myri10ge_get_msglevel }; -static int myri10ge_allocate_rings(struct net_device *dev) +static int myri10ge_allocate_rings(struct myri10ge_slice_state *ss) { - struct myri10ge_priv *mgp; + struct myri10ge_priv *mgp = ss->mgp; struct myri10ge_cmd cmd; + struct net_device *dev = mgp->dev; int tx_ring_size, rx_ring_size; int tx_ring_entries, rx_ring_entries; int i, status; size_t bytes; - mgp = netdev_priv(dev); - /* get ring sizes */ - status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd, 0); tx_ring_size = cmd.data0; status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd, 0); @@ -1607,144 +1642,142 @@ static int myri10ge_allocate_rings(struct net_device *dev) tx_ring_entries = tx_ring_size / sizeof(struct mcp_kreq_ether_send); rx_ring_entries = rx_ring_size / sizeof(struct mcp_dma_addr); - mgp->tx.mask = tx_ring_entries - 1; - mgp->rx_small.mask = mgp->rx_big.mask = rx_ring_entries - 1; + ss->tx.mask = tx_ring_entries - 1; + ss->rx_small.mask = ss->rx_big.mask = rx_ring_entries - 1; status = -ENOMEM; /* allocate the host shadow rings */ bytes = 8 + (MYRI10GE_MAX_SEND_DESC_TSO + 4) - * sizeof(*mgp->tx.req_list); - mgp->tx.req_bytes = kzalloc(bytes, GFP_KERNEL); - if (mgp->tx.req_bytes == NULL) + * sizeof(*ss->tx.req_list); + ss->tx.req_bytes = kzalloc(bytes, GFP_KERNEL); + if (ss->tx.req_bytes == NULL) goto abort_with_nothing; /* ensure req_list entries are aligned to 8 bytes */ - mgp->tx.req_list = (struct mcp_kreq_ether_send *) - ALIGN((unsigned long)mgp->tx.req_bytes, 8); + ss->tx.req_list = (struct mcp_kreq_ether_send *) + ALIGN((unsigned long)ss->tx.req_bytes, 8); - bytes = rx_ring_entries * sizeof(*mgp->rx_small.shadow); - mgp->rx_small.shadow = kzalloc(bytes, GFP_KERNEL); - if (mgp->rx_small.shadow == NULL) + bytes = rx_ring_entries * sizeof(*ss->rx_small.shadow); + ss->rx_small.shadow = kzalloc(bytes, GFP_KERNEL); + if (ss->rx_small.shadow == NULL) goto abort_with_tx_req_bytes; - bytes = rx_ring_entries * sizeof(*mgp->rx_big.shadow); - mgp->rx_big.shadow = kzalloc(bytes, GFP_KERNEL); - if (mgp->rx_big.shadow == NULL) + bytes = rx_ring_entries * sizeof(*ss->rx_big.shadow); + ss->rx_big.shadow = kzalloc(bytes, GFP_KERNEL); + if (ss->rx_big.shadow == NULL) goto abort_with_rx_small_shadow; /* allocate the host info rings */ - bytes = tx_ring_entries * sizeof(*mgp->tx.info); - mgp->tx.info = kzalloc(bytes, GFP_KERNEL); - if (mgp->tx.info == NULL) + bytes = tx_ring_entries * sizeof(*ss->tx.info); + ss->tx.info = kzalloc(bytes, GFP_KERNEL); + if (ss->tx.info == NULL) goto abort_with_rx_big_shadow; - bytes = rx_ring_entries * sizeof(*mgp->rx_small.info); - mgp->rx_small.info = kzalloc(bytes, GFP_KERNEL); - if (mgp->rx_small.info == NULL) + bytes = rx_ring_entries * sizeof(*ss->rx_small.info); + ss->rx_small.info = kzalloc(bytes, GFP_KERNEL); + if (ss->rx_small.info == NULL) goto abort_with_tx_info; - bytes = rx_ring_entries * sizeof(*mgp->rx_big.info); - mgp->rx_big.info = kzalloc(bytes, GFP_KERNEL); - if (mgp->rx_big.info == NULL) + bytes = rx_ring_entries * sizeof(*ss->rx_big.info); + ss->rx_big.info = kzalloc(bytes, GFP_KERNEL); + if (ss->rx_big.info == NULL) goto abort_with_rx_small_info; /* Fill the receive rings */ - mgp->rx_big.cnt = 0; - mgp->rx_small.cnt = 0; - mgp->rx_big.fill_cnt = 0; - mgp->rx_small.fill_cnt = 0; - mgp->rx_small.page_offset = MYRI10GE_ALLOC_SIZE; - mgp->rx_big.page_offset = MYRI10GE_ALLOC_SIZE; - mgp->rx_small.watchdog_needed = 0; - mgp->rx_big.watchdog_needed = 0; - myri10ge_alloc_rx_pages(mgp, &mgp->rx_small, + ss->rx_big.cnt = 0; + ss->rx_small.cnt = 0; + ss->rx_big.fill_cnt = 0; + ss->rx_small.fill_cnt = 0; + ss->rx_small.page_offset = MYRI10GE_ALLOC_SIZE; + ss->rx_big.page_offset = MYRI10GE_ALLOC_SIZE; + ss->rx_small.watchdog_needed = 0; + ss->rx_big.watchdog_needed = 0; + myri10ge_alloc_rx_pages(mgp, &ss->rx_small, mgp->small_bytes + MXGEFW_PAD, 0); - if (mgp->rx_small.fill_cnt < mgp->rx_small.mask + 1) { + if (ss->rx_small.fill_cnt < ss->rx_small.mask + 1) { printk(KERN_ERR "myri10ge: %s: alloced only %d small bufs\n", - dev->name, mgp->rx_small.fill_cnt); + dev->name, ss->rx_small.fill_cnt); goto abort_with_rx_small_ring; } - myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 0); - if (mgp->rx_big.fill_cnt < mgp->rx_big.mask + 1) { + myri10ge_alloc_rx_pages(mgp, &ss->rx_big, mgp->big_bytes, 0); + if (ss->rx_big.fill_cnt < ss->rx_big.mask + 1) { printk(KERN_ERR "myri10ge: %s: alloced only %d big bufs\n", - dev->name, mgp->rx_big.fill_cnt); + dev->name, ss->rx_big.fill_cnt); goto abort_with_rx_big_ring; } return 0; abort_with_rx_big_ring: - for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) { - int idx = i & mgp->rx_big.mask; - myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_big.info[idx], + for (i = ss->rx_big.cnt; i < ss->rx_big.fill_cnt; i++) { + int idx = i & ss->rx_big.mask; + myri10ge_unmap_rx_page(mgp->pdev, &ss->rx_big.info[idx], mgp->big_bytes); - put_page(mgp->rx_big.info[idx].page); + put_page(ss->rx_big.info[idx].page); } abort_with_rx_small_ring: - for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) { - int idx = i & mgp->rx_small.mask; - myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_small.info[idx], + for (i = ss->rx_small.cnt; i < ss->rx_small.fill_cnt; i++) { + int idx = i & ss->rx_small.mask; + myri10ge_unmap_rx_page(mgp->pdev, &ss->rx_small.info[idx], mgp->small_bytes + MXGEFW_PAD); - put_page(mgp->rx_small.info[idx].page); + put_page(ss->rx_small.info[idx].page); } - kfree(mgp->rx_big.info); + kfree(ss->rx_big.info); abort_with_rx_small_info: - kfree(mgp->rx_small.info); + kfree(ss->rx_small.info); abort_with_tx_info: - kfree(mgp->tx.info); + kfree(ss->tx.info); abort_with_rx_big_shadow: - kfree(mgp->rx_big.shadow); + kfree(ss->rx_big.shadow); abort_with_rx_small_shadow: - kfree(mgp->rx_small.shadow); + kfree(ss->rx_small.shadow); abort_with_tx_req_bytes: - kfree(mgp->tx.req_bytes); - mgp->tx.req_bytes = NULL; - mgp->tx.req_list = NULL; + kfree(ss->tx.req_bytes); + ss->tx.req_bytes = NULL; + ss->tx.req_list = NULL; abort_with_nothing: return status; } -static void myri10ge_free_rings(struct net_device *dev) +static void myri10ge_free_rings(struct myri10ge_slice_state *ss) { - struct myri10ge_priv *mgp; + struct myri10ge_priv *mgp = ss->mgp; struct sk_buff *skb; struct myri10ge_tx_buf *tx; int i, len, idx; - mgp = netdev_priv(dev); - - for (i = mgp->rx_big.cnt; i < mgp->rx_big.fill_cnt; i++) { - idx = i & mgp->rx_big.mask; - if (i == mgp->rx_big.fill_cnt - 1) - mgp->rx_big.info[idx].page_offset = MYRI10GE_ALLOC_SIZE; - myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_big.info[idx], + for (i = ss->rx_big.cnt; i < ss->rx_big.fill_cnt; i++) { + idx = i & ss->rx_big.mask; + if (i == ss->rx_big.fill_cnt - 1) + ss->rx_big.info[idx].page_offset = MYRI10GE_ALLOC_SIZE; + myri10ge_unmap_rx_page(mgp->pdev, &ss->rx_big.info[idx], mgp->big_bytes); - put_page(mgp->rx_big.info[idx].page); + put_page(ss->rx_big.info[idx].page); } - for (i = mgp->rx_small.cnt; i < mgp->rx_small.fill_cnt; i++) { - idx = i & mgp->rx_small.mask; - if (i == mgp->rx_small.fill_cnt - 1) - mgp->rx_small.info[idx].page_offset = + for (i = ss->rx_small.cnt; i < ss->rx_small.fill_cnt; i++) { + idx = i & ss->rx_small.mask; + if (i == ss->rx_small.fill_cnt - 1) + ss->rx_small.info[idx].page_offset = MYRI10GE_ALLOC_SIZE; - myri10ge_unmap_rx_page(mgp->pdev, &mgp->rx_small.info[idx], + myri10ge_unmap_rx_page(mgp->pdev, &ss->rx_small.info[idx], mgp->small_bytes + MXGEFW_PAD); - put_page(mgp->rx_small.info[idx].page); + put_page(ss->rx_small.info[idx].page); } - tx = &mgp->tx; + tx = &ss->tx; while (tx->done != tx->req) { idx = tx->done & tx->mask; skb = tx->info[idx].skb; @@ -1755,7 +1788,7 @@ static void myri10ge_free_rings(struct net_device *dev) len = pci_unmap_len(&tx->info[idx], len); pci_unmap_len_set(&tx->info[idx], len, 0); if (skb) { - mgp->stats.tx_dropped++; + ss->stats.tx_dropped++; dev_kfree_skb_any(skb); if (len) pci_unmap_single(mgp->pdev, @@ -1770,19 +1803,19 @@ static void myri10ge_free_rings(struct net_device *dev) PCI_DMA_TODEVICE); } } - kfree(mgp->rx_big.info); + kfree(ss->rx_big.info); - kfree(mgp->rx_small.info); + kfree(ss->rx_small.info); - kfree(mgp->tx.info); + kfree(ss->tx.info); - kfree(mgp->rx_big.shadow); + kfree(ss->rx_big.shadow); - kfree(mgp->rx_small.shadow); + kfree(ss->rx_small.shadow); - kfree(mgp->tx.req_bytes); - mgp->tx.req_bytes = NULL; - mgp->tx.req_list = NULL; + kfree(ss->tx.req_bytes); + ss->tx.req_bytes = NULL; + ss->tx.req_list = NULL; } static int myri10ge_request_irq(struct myri10ge_priv *mgp) @@ -1881,13 +1914,11 @@ myri10ge_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr, static int myri10ge_open(struct net_device *dev) { - struct myri10ge_priv *mgp; + struct myri10ge_priv *mgp = netdev_priv(dev); struct myri10ge_cmd cmd; struct net_lro_mgr *lro_mgr; int status, big_pow2; - mgp = netdev_priv(dev); - if (mgp->running != MYRI10GE_ETH_STOPPED) return -EBUSY; @@ -1924,16 +1955,16 @@ static int myri10ge_open(struct net_device *dev) /* get the lanai pointers to the send and receive rings */ status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd, 0); - mgp->tx.lanai = + mgp->ss.tx.lanai = (struct mcp_kreq_ether_send __iomem *)(mgp->sram + cmd.data0); status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET, &cmd, 0); - mgp->rx_small.lanai = + mgp->ss.rx_small.lanai = (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0); status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_BIG_RX_OFFSET, &cmd, 0); - mgp->rx_big.lanai = + mgp->ss.rx_big.lanai = (struct mcp_kreq_ether_recv __iomem *)(mgp->sram + cmd.data0); if (status != 0) { @@ -1945,15 +1976,15 @@ static int myri10ge_open(struct net_device *dev) } if (myri10ge_wcfifo && mgp->wc_enabled) { - mgp->tx.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_SEND_4; - mgp->rx_small.wc_fifo = + mgp->ss.tx.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_SEND_4; + mgp->ss.rx_small.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_SMALL; - mgp->rx_big.wc_fifo = + mgp->ss.rx_big.wc_fifo = (u8 __iomem *) mgp->sram + MXGEFW_ETH_RECV_BIG; } else { - mgp->tx.wc_fifo = NULL; - mgp->rx_small.wc_fifo = NULL; - mgp->rx_big.wc_fifo = NULL; + mgp->ss.tx.wc_fifo = NULL; + mgp->ss.rx_small.wc_fifo = NULL; + mgp->ss.rx_big.wc_fifo = NULL; } /* Firmware needs the big buff size as a power of 2. Lie and @@ -1970,7 +2001,7 @@ static int myri10ge_open(struct net_device *dev) mgp->big_bytes = big_pow2; } - status = myri10ge_allocate_rings(dev); + status = myri10ge_allocate_rings(&mgp->ss); if (status != 0) goto abort_with_irq; @@ -1989,12 +2020,12 @@ static int myri10ge_open(struct net_device *dev) goto abort_with_rings; } - cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->fw_stats_bus); - cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->fw_stats_bus); + cmd.data0 = MYRI10GE_LOWPART_TO_U32(mgp->ss.fw_stats_bus); + cmd.data1 = MYRI10GE_HIGHPART_TO_U32(mgp->ss.fw_stats_bus); cmd.data2 = sizeof(struct mcp_irq_data); status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA_V2, &cmd, 0); if (status == -ENOSYS) { - dma_addr_t bus = mgp->fw_stats_bus; + dma_addr_t bus = mgp->ss.fw_stats_bus; bus += offsetof(struct mcp_irq_data, send_done_count); cmd.data0 = MYRI10GE_LOWPART_TO_U32(bus); cmd.data1 = MYRI10GE_HIGHPART_TO_U32(bus); @@ -2015,20 +2046,20 @@ static int myri10ge_open(struct net_device *dev) mgp->link_state = ~0U; mgp->rdma_tags_available = 15; - lro_mgr = &mgp->rx_done.lro_mgr; + lro_mgr = &mgp->ss.rx_done.lro_mgr; lro_mgr->dev = dev; lro_mgr->features = LRO_F_NAPI; lro_mgr->ip_summed = CHECKSUM_COMPLETE; lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; lro_mgr->max_desc = MYRI10GE_MAX_LRO_DESCRIPTORS; - lro_mgr->lro_arr = mgp->rx_done.lro_desc; + lro_mgr->lro_arr = mgp->ss.rx_done.lro_desc; lro_mgr->get_frag_header = myri10ge_get_frag_header; lro_mgr->max_aggr = myri10ge_lro_max_pkts; lro_mgr->frag_align_pad = 2; if (lro_mgr->max_aggr > MAX_SKB_FRAGS) lro_mgr->max_aggr = MAX_SKB_FRAGS; - napi_enable(&mgp->napi); /* must happen prior to any irq */ + napi_enable(&mgp->ss.napi); /* must happen prior to any irq */ status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd, 0); if (status) { @@ -2037,8 +2068,8 @@ static int myri10ge_open(struct net_device *dev) goto abort_with_rings; } - mgp->wake_queue = 0; - mgp->stop_queue = 0; + mgp->ss.tx.wake_queue = 0; + mgp->ss.tx.stop_queue = 0; mgp->running = MYRI10GE_ETH_RUNNING; mgp->watchdog_timer.expires = jiffies + myri10ge_watchdog_timeout * HZ; add_timer(&mgp->watchdog_timer); @@ -2046,7 +2077,7 @@ static int myri10ge_open(struct net_device *dev) return 0; abort_with_rings: - myri10ge_free_rings(dev); + myri10ge_free_rings(&mgp->ss); abort_with_irq: myri10ge_free_irq(mgp); @@ -2058,21 +2089,19 @@ abort_with_nothing: static int myri10ge_close(struct net_device *dev) { - struct myri10ge_priv *mgp; + struct myri10ge_priv *mgp = netdev_priv(dev); struct myri10ge_cmd cmd; int status, old_down_cnt; - mgp = netdev_priv(dev); - if (mgp->running != MYRI10GE_ETH_RUNNING) return 0; - if (mgp->tx.req_bytes == NULL) + if (mgp->ss.tx.req_bytes == NULL) return 0; del_timer_sync(&mgp->watchdog_timer); mgp->running = MYRI10GE_ETH_STOPPING; - napi_disable(&mgp->napi); + napi_disable(&mgp->ss.napi); netif_carrier_off(dev); netif_stop_queue(dev); old_down_cnt = mgp->down_cnt; @@ -2088,7 +2117,7 @@ static int myri10ge_close(struct net_device *dev) netif_tx_disable(dev); myri10ge_free_irq(mgp); - myri10ge_free_rings(dev); + myri10ge_free_rings(&mgp->ss); mgp->running = MYRI10GE_ETH_STOPPED; return 0; @@ -2184,7 +2213,7 @@ myri10ge_submit_req_wc(struct myri10ge_tx_buf *tx, /* * Transmit a packet. We need to split the packet so that a single - * segment does not cross myri10ge->tx.boundary, so this makes segment + * segment does not cross myri10ge->tx_boundary, so this makes segment * counting tricky. So rather than try to count segments up front, we * just give up if there are too few segments to hold a reasonably * fragmented packet currently available. If we run @@ -2195,8 +2224,9 @@ myri10ge_submit_req_wc(struct myri10ge_tx_buf *tx, static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) { struct myri10ge_priv *mgp = netdev_priv(dev); + struct myri10ge_slice_state *ss; struct mcp_kreq_ether_send *req; - struct myri10ge_tx_buf *tx = &mgp->tx; + struct myri10ge_tx_buf *tx; struct skb_frag_struct *frag; dma_addr_t bus; u32 low; @@ -2207,6 +2237,9 @@ static int myri10ge_xmit(struct sk_buff *skb, struct net_device *dev) int cum_len, seglen, boundary, rdma_count; u8 flags, odd_flag; + /* always transmit through slot 0 */ + ss = &mgp->ss; + tx = &ss->tx; again: req = tx->req_list; avail = tx->mask - 1 - (tx->req - tx->done); @@ -2221,7 +2254,7 @@ again: if ((unlikely(avail < max_segments))) { /* we are out of transmit resources */ - mgp->stop_queue++; + tx->stop_queue++; netif_stop_queue(dev); return 1; } @@ -2283,7 +2316,7 @@ again: if (skb_padto(skb, ETH_ZLEN)) { /* The packet is gone, so we must * return 0 */ - mgp->stats.tx_dropped += 1; + ss->stats.tx_dropped += 1; return 0; } /* adjust the len to account for the zero pad @@ -2325,7 +2358,7 @@ again: while (1) { /* Break the SKB or Fragment up into pieces which - * do not cross mgp->tx.boundary */ + * do not cross mgp->tx_boundary */ low = MYRI10GE_LOWPART_TO_U32(bus); high_swapped = htonl(MYRI10GE_HIGHPART_TO_U32(bus)); while (len) { @@ -2335,7 +2368,8 @@ again: if (unlikely(count == max_segments)) goto abort_linearize; - boundary = (low + tx->boundary) & ~(tx->boundary - 1); + boundary = + (low + mgp->tx_boundary) & ~(mgp->tx_boundary - 1); seglen = boundary - low; if (seglen > len) seglen = len; @@ -2419,7 +2453,7 @@ again: myri10ge_submit_req_wc(tx, tx->req_list, count); tx->pkt_start++; if ((avail - count) < MXGEFW_MAX_SEND_DESC) { - mgp->stop_queue++; + tx->stop_queue++; netif_stop_queue(dev); } dev->trans_start = jiffies; @@ -2461,12 +2495,12 @@ abort_linearize: if (skb_linearize(skb)) goto drop; - mgp->tx_linearized++; + tx->linearized++; goto again; drop: dev_kfree_skb_any(skb); - mgp->stats.tx_dropped += 1; + ss->stats.tx_dropped += 1; return 0; } @@ -2474,7 +2508,7 @@ drop: static int myri10ge_sw_tso(struct sk_buff *skb, struct net_device *dev) { struct sk_buff *segs, *curr; - struct myri10ge_priv *mgp = dev->priv; + struct myri10ge_priv *mgp = netdev_priv(dev); int status; segs = skb_gso_segment(skb, dev->features & ~NETIF_F_TSO6); @@ -2514,14 +2548,13 @@ static struct net_device_stats *myri10ge_get_stats(struct net_device *dev) static void myri10ge_set_multicast_list(struct net_device *dev) { + struct myri10ge_priv *mgp = netdev_priv(dev); struct myri10ge_cmd cmd; - struct myri10ge_priv *mgp; struct dev_mc_list *mc_list; __be32 data[2] = { 0, 0 }; int err; DECLARE_MAC_BUF(mac); - mgp = netdev_priv(dev); /* can be called from atomic contexts, * pass 1 to force atomicity in myri10ge_send_cmd() */ myri10ge_change_promisc(mgp, dev->flags & IFF_PROMISC, 1); @@ -2723,9 +2756,9 @@ static void myri10ge_enable_ecrc(struct myri10ge_priv *mgp) * already been enabled, then it must use a firmware image which works * around unaligned completion packets (myri10ge_ethp_z8e.dat), and it * should also ensure that it never gives the device a Read-DMA which is - * larger than 2KB by setting the tx.boundary to 2KB. If ECRC is + * larger than 2KB by setting the tx_boundary to 2KB. If ECRC is * enabled, then the driver should use the aligned (myri10ge_eth_z8e.dat) - * firmware image, and set tx.boundary to 4KB. + * firmware image, and set tx_boundary to 4KB. */ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) @@ -2734,7 +2767,7 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) struct device *dev = &pdev->dev; int status; - mgp->tx.boundary = 4096; + mgp->tx_boundary = 4096; /* * Verify the max read request size was set to 4KB * before trying the test with 4KB. @@ -2746,7 +2779,7 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) } if (status != 4096) { dev_warn(dev, "Max Read Request size != 4096 (%d)\n", status); - mgp->tx.boundary = 2048; + mgp->tx_boundary = 2048; } /* * load the optimized firmware (which assumes aligned PCIe @@ -2779,7 +2812,7 @@ static void myri10ge_firmware_probe(struct myri10ge_priv *mgp) "Please install up to date fw\n"); abort: /* fall back to using the unaligned firmware */ - mgp->tx.boundary = 2048; + mgp->tx_boundary = 2048; mgp->fw_name = myri10ge_fw_unaligned; } @@ -2800,7 +2833,7 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) if (link_width < 8) { dev_info(&mgp->pdev->dev, "PCIE x%d Link\n", link_width); - mgp->tx.boundary = 4096; + mgp->tx_boundary = 4096; mgp->fw_name = myri10ge_fw_aligned; } else { myri10ge_firmware_probe(mgp); @@ -2809,12 +2842,12 @@ static void myri10ge_select_firmware(struct myri10ge_priv *mgp) if (myri10ge_force_firmware == 1) { dev_info(&mgp->pdev->dev, "Assuming aligned completions (forced)\n"); - mgp->tx.boundary = 4096; + mgp->tx_boundary = 4096; mgp->fw_name = myri10ge_fw_aligned; } else { dev_info(&mgp->pdev->dev, "Assuming unaligned completions (forced)\n"); - mgp->tx.boundary = 2048; + mgp->tx_boundary = 2048; mgp->fw_name = myri10ge_fw_unaligned; } } @@ -2931,6 +2964,7 @@ static void myri10ge_watchdog(struct work_struct *work) { struct myri10ge_priv *mgp = container_of(work, struct myri10ge_priv, watchdog_work); + struct myri10ge_tx_buf *tx; u32 reboot; int status; u16 cmd, vendor; @@ -2980,15 +3014,16 @@ static void myri10ge_watchdog(struct work_struct *work) printk(KERN_ERR "myri10ge: %s: device timeout, resetting\n", mgp->dev->name); + tx = &mgp->ss.tx; printk(KERN_INFO "myri10ge: %s: %d %d %d %d %d\n", - mgp->dev->name, mgp->tx.req, mgp->tx.done, - mgp->tx.pkt_start, mgp->tx.pkt_done, - (int)ntohl(mgp->fw_stats->send_done_count)); + mgp->dev->name, tx->req, tx->done, + tx->pkt_start, tx->pkt_done, + (int)ntohl(mgp->ss.fw_stats->send_done_count)); msleep(2000); printk(KERN_INFO "myri10ge: %s: %d %d %d %d %d\n", - mgp->dev->name, mgp->tx.req, mgp->tx.done, - mgp->tx.pkt_start, mgp->tx.pkt_done, - (int)ntohl(mgp->fw_stats->send_done_count)); + mgp->dev->name, tx->req, tx->done, + tx->pkt_start, tx->pkt_done, + (int)ntohl(mgp->ss.fw_stats->send_done_count)); } rtnl_lock(); myri10ge_close(mgp->dev); @@ -3011,28 +3046,31 @@ static void myri10ge_watchdog(struct work_struct *work) static void myri10ge_watchdog_timer(unsigned long arg) { struct myri10ge_priv *mgp; + struct myri10ge_slice_state *ss; u32 rx_pause_cnt; mgp = (struct myri10ge_priv *)arg; - if (mgp->rx_small.watchdog_needed) { - myri10ge_alloc_rx_pages(mgp, &mgp->rx_small, + rx_pause_cnt = ntohl(mgp->ss.fw_stats->dropped_pause); + + ss = &mgp->ss; + if (ss->rx_small.watchdog_needed) { + myri10ge_alloc_rx_pages(mgp, &ss->rx_small, mgp->small_bytes + MXGEFW_PAD, 1); - if (mgp->rx_small.fill_cnt - mgp->rx_small.cnt >= + if (ss->rx_small.fill_cnt - ss->rx_small.cnt >= myri10ge_fill_thresh) - mgp->rx_small.watchdog_needed = 0; + ss->rx_small.watchdog_needed = 0; } - if (mgp->rx_big.watchdog_needed) { - myri10ge_alloc_rx_pages(mgp, &mgp->rx_big, mgp->big_bytes, 1); - if (mgp->rx_big.fill_cnt - mgp->rx_big.cnt >= + if (ss->rx_big.watchdog_needed) { + myri10ge_alloc_rx_pages(mgp, &ss->rx_big, mgp->big_bytes, 1); + if (ss->rx_big.fill_cnt - ss->rx_big.cnt >= myri10ge_fill_thresh) - mgp->rx_big.watchdog_needed = 0; + ss->rx_big.watchdog_needed = 0; } - rx_pause_cnt = ntohl(mgp->fw_stats->dropped_pause); - if (mgp->tx.req != mgp->tx.done && - mgp->tx.done == mgp->watchdog_tx_done && - mgp->watchdog_tx_req != mgp->watchdog_tx_done) { + if (ss->tx.req != ss->tx.done && + ss->tx.done == ss->watchdog_tx_done && + ss->watchdog_tx_req != ss->watchdog_tx_done) { /* nic seems like it might be stuck.. */ if (rx_pause_cnt != mgp->watchdog_pause) { if (net_ratelimit()) @@ -3047,8 +3085,8 @@ static void myri10ge_watchdog_timer(unsigned long arg) /* rearm timer */ mod_timer(&mgp->watchdog_timer, jiffies + myri10ge_watchdog_timeout * HZ); - mgp->watchdog_tx_done = mgp->tx.done; - mgp->watchdog_tx_req = mgp->tx.req; + ss->watchdog_tx_done = ss->tx.done; + ss->watchdog_tx_req = ss->tx.req; mgp->watchdog_pause = rx_pause_cnt; } @@ -3072,7 +3110,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) mgp = netdev_priv(netdev); mgp->dev = netdev; - netif_napi_add(netdev, &mgp->napi, myri10ge_poll, myri10ge_napi_weight); + netif_napi_add(netdev, &mgp->ss.napi, myri10ge_poll, myri10ge_napi_weight); mgp->pdev = pdev; mgp->csum_flag = MXGEFW_FLAGS_CKSUM; mgp->pause = myri10ge_flow_control; @@ -3118,9 +3156,9 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (mgp->cmd == NULL) goto abort_with_netdev; - mgp->fw_stats = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->fw_stats), - &mgp->fw_stats_bus, GFP_KERNEL); - if (mgp->fw_stats == NULL) + mgp->ss.fw_stats = dma_alloc_coherent(&pdev->dev, sizeof(*mgp->ss.fw_stats), + &mgp->ss.fw_stats_bus, GFP_KERNEL); + if (mgp->ss.fw_stats == NULL) goto abort_with_cmd; mgp->board_span = pci_resource_len(pdev, 0); @@ -3160,12 +3198,12 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->dev_addr[i] = mgp->mac_addr[i]; /* allocate rx done ring */ - bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry); - mgp->rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes, - &mgp->rx_done.bus, GFP_KERNEL); - if (mgp->rx_done.entry == NULL) + bytes = myri10ge_max_intr_slots * sizeof(*mgp->ss.rx_done.entry); + mgp->ss.rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes, + &mgp->ss.rx_done.bus, GFP_KERNEL); + if (mgp->ss.rx_done.entry == NULL) goto abort_with_ioremap; - memset(mgp->rx_done.entry, 0, bytes); + memset(mgp->ss.rx_done.entry, 0, bytes); myri10ge_select_firmware(mgp); @@ -3225,7 +3263,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } dev_info(dev, "%s IRQ %d, tx bndry %d, fw %s, WC %s\n", (mgp->msi_enabled ? "MSI" : "xPIC"), - netdev->irq, mgp->tx.boundary, mgp->fw_name, + netdev->irq, mgp->tx_boundary, mgp->fw_name, (mgp->wc_enabled ? "Enabled" : "Disabled")); return 0; @@ -3237,9 +3275,9 @@ abort_with_firmware: myri10ge_dummy_rdma(mgp, 0); abort_with_rx_done: - bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry); + bytes = myri10ge_max_intr_slots * sizeof(*mgp->ss.rx_done.entry); dma_free_coherent(&pdev->dev, bytes, - mgp->rx_done.entry, mgp->rx_done.bus); + mgp->ss.rx_done.entry, mgp->ss.rx_done.bus); abort_with_ioremap: iounmap(mgp->sram); @@ -3249,8 +3287,8 @@ abort_with_wc: if (mgp->mtrr >= 0) mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span); #endif - dma_free_coherent(&pdev->dev, sizeof(*mgp->fw_stats), - mgp->fw_stats, mgp->fw_stats_bus); + dma_free_coherent(&pdev->dev, sizeof(*mgp->ss.fw_stats), + mgp->ss.fw_stats, mgp->ss.fw_stats_bus); abort_with_cmd: dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), @@ -3288,9 +3326,9 @@ static void myri10ge_remove(struct pci_dev *pdev) /* avoid a memory leak */ pci_restore_state(pdev); - bytes = myri10ge_max_intr_slots * sizeof(*mgp->rx_done.entry); + bytes = myri10ge_max_intr_slots * sizeof(*mgp->ss.rx_done.entry); dma_free_coherent(&pdev->dev, bytes, - mgp->rx_done.entry, mgp->rx_done.bus); + mgp->ss.rx_done.entry, mgp->ss.rx_done.bus); iounmap(mgp->sram); @@ -3298,8 +3336,8 @@ static void myri10ge_remove(struct pci_dev *pdev) if (mgp->mtrr >= 0) mtrr_del(mgp->mtrr, mgp->iomem_base, mgp->board_span); #endif - dma_free_coherent(&pdev->dev, sizeof(*mgp->fw_stats), - mgp->fw_stats, mgp->fw_stats_bus); + dma_free_coherent(&pdev->dev, sizeof(*mgp->ss.fw_stats), + mgp->ss.fw_stats, mgp->ss.fw_stats_bus); dma_free_coherent(&pdev->dev, sizeof(*mgp->cmd), mgp->cmd, mgp->cmd_bus); -- cgit v1.1 From fa0a90d96b08856203435b051dd1c155b58ccd0f Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 9 May 2008 02:20:25 +0200 Subject: myri10ge: cleanup retrieving of firmware capabilities Add myri10ge_get_firmware_capabilities() to retrieve TSO6 and interrupt slots capabilities from the firmware. Signed-off-by: Brice Goglin Signed-off-by: Andrew Gallatin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 42 ++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 5edcbfe..054168f 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -194,6 +194,7 @@ struct myri10ge_priv { int csum_flag; /* rx_csums? */ int small_bytes; int big_bytes; + int max_intr_slots; struct net_device *dev; struct net_device_stats stats; spinlock_t stats_lock; @@ -634,13 +635,38 @@ static int myri10ge_adopt_running_firmware(struct myri10ge_priv *mgp) return status; } +int myri10ge_get_firmware_capabilities(struct myri10ge_priv *mgp) +{ + struct myri10ge_cmd cmd; + int status; + + /* probe for IPv6 TSO support */ + mgp->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE, + &cmd, 0); + if (status == 0) { + mgp->max_tso6 = cmd.data0; + mgp->features |= NETIF_F_TSO6; + } + + status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd, 0); + if (status != 0) { + dev_err(&mgp->pdev->dev, + "failed MXGEFW_CMD_GET_RX_RING_SIZE\n"); + return -ENXIO; + } + + mgp->max_intr_slots = 2 * (cmd.data0 / sizeof(struct mcp_dma_addr)); + + return 0; +} + static int myri10ge_load_firmware(struct myri10ge_priv *mgp) { char __iomem *submit; __be32 buf[16] __attribute__ ((__aligned__(8))); u32 dma_low, dma_high, size; int status, i; - struct myri10ge_cmd cmd; size = 0; status = myri10ge_load_hotplug_firmware(mgp, &size); @@ -672,6 +698,8 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) mgp->fw_name = "adopted"; mgp->tx_boundary = 2048; + myri10ge_dummy_rdma(mgp, 1); + status = myri10ge_get_firmware_capabilities(mgp); return status; } @@ -714,18 +742,10 @@ static int myri10ge_load_firmware(struct myri10ge_priv *mgp) dev_err(&mgp->pdev->dev, "handoff failed\n"); return -ENXIO; } - dev_info(&mgp->pdev->dev, "handoff confirmed\n"); myri10ge_dummy_rdma(mgp, 1); + status = myri10ge_get_firmware_capabilities(mgp); - /* probe for IPv6 TSO support */ - mgp->features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO; - status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_TSO6_HDR_SIZE, - &cmd, 0); - if (status == 0) { - mgp->max_tso6 = cmd.data0; - mgp->features |= NETIF_F_TSO6; - } - return 0; + return status; } static int myri10ge_update_mac_address(struct myri10ge_priv *mgp, u8 * addr) -- cgit v1.1 From 014377a1df693ff30a9e8b69f0bbb0a38e601f75 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Fri, 9 May 2008 02:20:47 +0200 Subject: myri10ge: fix the number of interrupt slots Fix a long-standing bug/misunderstanding between the driver and the firmware. The size of the interrupt queue must be set to the number of rx slots (big + small), and it should never have been a tunable. Setting it too small results in chaos. Signed-off-by: Brice Goglin Signed-off-by: Andrew Gallatin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 054168f..c91b12e 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -253,10 +253,6 @@ static int myri10ge_ecrc_enable = 1; module_param(myri10ge_ecrc_enable, int, S_IRUGO); MODULE_PARM_DESC(myri10ge_ecrc_enable, "Enable Extended CRC on PCI-E"); -static int myri10ge_max_intr_slots = 1024; -module_param(myri10ge_max_intr_slots, int, S_IRUGO); -MODULE_PARM_DESC(myri10ge_max_intr_slots, "Interrupt queue slots"); - static int myri10ge_small_bytes = -1; /* -1 == auto */ module_param(myri10ge_small_bytes, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(myri10ge_small_bytes, "Threshold of small packets"); @@ -879,7 +875,7 @@ static int myri10ge_reset(struct myri10ge_priv *mgp) /* Now exchange information about interrupts */ - bytes = myri10ge_max_intr_slots * sizeof(*mgp->ss.rx_done.entry); + bytes = mgp->max_intr_slots * sizeof(*mgp->ss.rx_done.entry); memset(mgp->ss.rx_done.entry, 0, bytes); cmd.data0 = (u32) bytes; status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd, 0); @@ -1217,7 +1213,7 @@ myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, int budget) rx_packets += rx_ok; rx_bytes += rx_ok * (unsigned long)length; cnt++; - idx = cnt & (myri10ge_max_intr_slots - 1); + idx = cnt & (mgp->max_intr_slots - 1); work_done++; } rx_done->idx = idx; @@ -3218,7 +3214,7 @@ static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) netdev->dev_addr[i] = mgp->mac_addr[i]; /* allocate rx done ring */ - bytes = myri10ge_max_intr_slots * sizeof(*mgp->ss.rx_done.entry); + bytes = mgp->max_intr_slots * sizeof(*mgp->ss.rx_done.entry); mgp->ss.rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes, &mgp->ss.rx_done.bus, GFP_KERNEL); if (mgp->ss.rx_done.entry == NULL) @@ -3295,7 +3291,7 @@ abort_with_firmware: myri10ge_dummy_rdma(mgp, 0); abort_with_rx_done: - bytes = myri10ge_max_intr_slots * sizeof(*mgp->ss.rx_done.entry); + bytes = mgp->max_intr_slots * sizeof(*mgp->ss.rx_done.entry); dma_free_coherent(&pdev->dev, bytes, mgp->ss.rx_done.entry, mgp->ss.rx_done.bus); @@ -3346,7 +3342,7 @@ static void myri10ge_remove(struct pci_dev *pdev) /* avoid a memory leak */ pci_restore_state(pdev); - bytes = myri10ge_max_intr_slots * sizeof(*mgp->ss.rx_done.entry); + bytes = mgp->max_intr_slots * sizeof(*mgp->ss.rx_done.entry); dma_free_coherent(&pdev->dev, bytes, mgp->ss.rx_done.entry, mgp->ss.rx_done.bus); -- cgit v1.1 From 48c4b6dbb7e246957e13302668acf7c77e4f8b3a Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Tue, 6 May 2008 19:25:56 -0700 Subject: cxgb3 - fix port up/down error path Fix faiures path when ports are stopped and restarted in EEH recovery. Signed-off-by: Divy Le Ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/adapter.h | 1 + drivers/net/cxgb3/cxgb3_main.c | 32 +++++++++++++++++--------------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index 4fdb13f..acebe43 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h @@ -71,6 +71,7 @@ enum { /* adapter flags */ USING_MSIX = (1 << 2), QUEUES_BOUND = (1 << 3), TP_PARITY_INIT = (1 << 4), + NAPI_INIT = (1 << 5), }; struct fl_pg_chunk { diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index ce949d5..d67fc10 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -421,6 +421,13 @@ static void init_napi(struct adapter *adap) netif_napi_add(qs->netdev, &qs->napi, qs->napi.poll, 64); } + + /* + * netif_napi_add() can be called only once per napi_struct because it + * adds each new napi_struct to a list. Be careful not to call it a + * second time, e.g., during EEH recovery, by making a note of it. + */ + adap->flags |= NAPI_INIT; } /* @@ -896,7 +903,8 @@ static int cxgb_up(struct adapter *adap) goto out; setup_rss(adap); - init_napi(adap); + if (!(adap->flags & NAPI_INIT)) + init_napi(adap); adap->flags |= FULL_INIT_DONE; } @@ -999,7 +1007,7 @@ static int offload_open(struct net_device *dev) return 0; if (!adap_up && (err = cxgb_up(adapter)) < 0) - return err; + goto out; t3_tp_set_offload_mode(adapter, 1); tdev->lldev = adapter->port[0]; @@ -1061,10 +1069,8 @@ static int cxgb_open(struct net_device *dev) int other_ports = adapter->open_device_map & PORT_MASK; int err; - if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) { - quiesce_rx(adapter); + if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) return err; - } set_bit(pi->port_id, &adapter->open_device_map); if (is_offload(adapter) && !ofld_disable) { @@ -2431,7 +2437,7 @@ static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev, pci_disable_device(pdev); - /* Request a slot slot reset. */ + /* Request a slot reset. */ return PCI_ERS_RESULT_NEED_RESET; } @@ -2448,13 +2454,16 @@ static pci_ers_result_t t3_io_slot_reset(struct pci_dev *pdev) if (pci_enable_device(pdev)) { dev_err(&pdev->dev, "Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; + goto err; } pci_set_master(pdev); - t3_prep_adapter(adapter, adapter->params.info, 1); + if (t3_prep_adapter(adapter, adapter->params.info, 1)) + goto err; return PCI_ERS_RESULT_RECOVERED; +err: + return PCI_ERS_RESULT_DISCONNECT; } /** @@ -2483,13 +2492,6 @@ static void t3_io_resume(struct pci_dev *pdev) netif_device_attach(netdev); } } - - if (is_offload(adapter)) { - __set_bit(OFFLOAD_DEVMAP_BIT, &adapter->registered_device_map); - if (offload_open(adapter->port[0])) - printk(KERN_WARNING - "Could not bring back offload capabilities\n"); - } } static struct pci_error_handlers t3_err_handler = { -- cgit v1.1 From 204e2f98c2d13f869b8541f3c57c7314f75cab11 Mon Sep 17 00:00:00 2001 From: Divy Le Ray Date: Tue, 6 May 2008 19:26:01 -0700 Subject: cxgb3 - fix EEH Reset the chip when the PCI link goes down. Preserve the napi structure when a sge qset's resources are freed. Replay only HW initialization when the chip comes out of reset. Signed-off-by: Divy Le ray Signed-off-by: Jeff Garzik --- drivers/net/cxgb3/common.h | 1 + drivers/net/cxgb3/cxgb3_main.c | 10 ++++++---- drivers/net/cxgb3/regs.h | 8 ++++++++ drivers/net/cxgb3/sge.c | 29 +++++++++++++++++++++++++++-- drivers/net/cxgb3/t3_hw.c | 28 ++++++++++++++++++++++++++++ 5 files changed, 70 insertions(+), 6 deletions(-) diff --git a/drivers/net/cxgb3/common.h b/drivers/net/cxgb3/common.h index 91ee727..579bee4 100644 --- a/drivers/net/cxgb3/common.h +++ b/drivers/net/cxgb3/common.h @@ -698,6 +698,7 @@ void mac_prep(struct cmac *mac, struct adapter *adapter, int index); void early_hw_init(struct adapter *adapter, const struct adapter_info *ai); int t3_prep_adapter(struct adapter *adapter, const struct adapter_info *ai, int reset); +int t3_replay_prep_adapter(struct adapter *adapter); void t3_led_ready(struct adapter *adapter); void t3_fatal_err(struct adapter *adapter); void t3_set_vlan_accel(struct adapter *adapter, unsigned int ports, int on); diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index d67fc10..3a31272 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -2430,9 +2430,6 @@ static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev, test_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map)) offload_close(&adapter->tdev); - /* Free sge resources */ - t3_free_sge_resources(adapter); - adapter->flags &= ~FULL_INIT_DONE; pci_disable_device(pdev); @@ -2457,8 +2454,12 @@ static pci_ers_result_t t3_io_slot_reset(struct pci_dev *pdev) goto err; } pci_set_master(pdev); + pci_restore_state(pdev); + + /* Free sge resources */ + t3_free_sge_resources(adapter); - if (t3_prep_adapter(adapter, adapter->params.info, 1)) + if (t3_replay_prep_adapter(adapter)) goto err; return PCI_ERS_RESULT_RECOVERED; @@ -2610,6 +2611,7 @@ static int __devinit init_one(struct pci_dev *pdev, } pci_set_master(pdev); + pci_save_state(pdev); mmio_start = pci_resource_start(pdev, 0); mmio_len = pci_resource_len(pdev, 0); diff --git a/drivers/net/cxgb3/regs.h b/drivers/net/cxgb3/regs.h index 02dbbb3..5671788 100644 --- a/drivers/net/cxgb3/regs.h +++ b/drivers/net/cxgb3/regs.h @@ -444,6 +444,14 @@ #define A_PCIE_CFG 0x88 +#define S_ENABLELINKDWNDRST 21 +#define V_ENABLELINKDWNDRST(x) ((x) << S_ENABLELINKDWNDRST) +#define F_ENABLELINKDWNDRST V_ENABLELINKDWNDRST(1U) + +#define S_ENABLELINKDOWNRST 20 +#define V_ENABLELINKDOWNRST(x) ((x) << S_ENABLELINKDOWNRST) +#define F_ENABLELINKDOWNRST V_ENABLELINKDOWNRST(1U) + #define S_PCIE_CLIDECEN 16 #define V_PCIE_CLIDECEN(x) ((x) << S_PCIE_CLIDECEN) #define F_PCIE_CLIDECEN V_PCIE_CLIDECEN(1U) diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 98a6bbd..796eb30 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c @@ -539,6 +539,31 @@ static void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size, } /** + * t3_reset_qset - reset a sge qset + * @q: the queue set + * + * Reset the qset structure. + * the NAPI structure is preserved in the event of + * the qset's reincarnation, for example during EEH recovery. + */ +static void t3_reset_qset(struct sge_qset *q) +{ + if (q->adap && + !(q->adap->flags & NAPI_INIT)) { + memset(q, 0, sizeof(*q)); + return; + } + + q->adap = NULL; + memset(&q->rspq, 0, sizeof(q->rspq)); + memset(q->fl, 0, sizeof(struct sge_fl) * SGE_RXQ_PER_SET); + memset(q->txq, 0, sizeof(struct sge_txq) * SGE_TXQ_PER_SET); + q->txq_stopped = 0; + memset(&q->tx_reclaim_timer, 0, sizeof(q->tx_reclaim_timer)); +} + + +/** * free_qset - free the resources of an SGE queue set * @adapter: the adapter owning the queue set * @q: the queue set @@ -594,7 +619,7 @@ static void t3_free_qset(struct adapter *adapter, struct sge_qset *q) q->rspq.desc, q->rspq.phys_addr); } - memset(q, 0, sizeof(*q)); + t3_reset_qset(q); } /** @@ -1365,7 +1390,7 @@ static void restart_ctrlq(unsigned long data) */ int t3_mgmt_tx(struct adapter *adap, struct sk_buff *skb) { - int ret; + int ret; local_bh_disable(); ret = ctrl_xmit(adap, &adap->sge.qs[0].txq[TXQ_CTRL], skb); local_bh_enable(); diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index a99496a..d405a93 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c @@ -3264,6 +3264,7 @@ static void config_pcie(struct adapter *adap) t3_write_reg(adap, A_PCIE_PEX_ERR, 0xffffffff); t3_set_reg_field(adap, A_PCIE_CFG, 0, + F_ENABLELINKDWNDRST | F_ENABLELINKDOWNRST | F_PCIE_DMASTOPEN | F_PCIE_CLIDECEN); } @@ -3655,3 +3656,30 @@ void t3_led_ready(struct adapter *adapter) t3_set_reg_field(adapter, A_T3DBG_GPIO_EN, F_GPIO0_OUT_VAL, F_GPIO0_OUT_VAL); } + +int t3_replay_prep_adapter(struct adapter *adapter) +{ + const struct adapter_info *ai = adapter->params.info; + unsigned int i, j = 0; + int ret; + + early_hw_init(adapter, ai); + ret = init_parity(adapter); + if (ret) + return ret; + + for_each_port(adapter, i) { + struct port_info *p = adap2pinfo(adapter, i); + while (!adapter->params.vpd.port_type[j]) + ++j; + + p->port_type->phy_prep(&p->phy, adapter, ai->phy_base_addr + j, + ai->mdio_ops); + + p->phy.ops->power_down(&p->phy, 1); + ++j; + } + +return 0; +} + -- cgit v1.1 From ad5da7ab7be0a510ae69d533edf573d1ca6eec4b Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Wed, 7 May 2008 13:20:55 -0500 Subject: gianfar: Fix a bug where the pointer never moves for dma_unmap... The loop that unmaps all of the TX Buffer Descriptors never actually moves the txbd pointer, so we were just repeatedly unmapping the first one. Signed-off-by: Andy Fleming Signed-off-by: Jeff Garzik --- drivers/net/gianfar.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 6f22f06..25bdd08 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -635,6 +635,8 @@ static void free_skb_resources(struct gfar_private *priv) dev_kfree_skb_any(priv->tx_skbuff[i]); priv->tx_skbuff[i] = NULL; } + + txbdp++; } kfree(priv->tx_skbuff); -- cgit v1.1 From 3c82c30cd5963a4523a6ec5f32fc2d20a5bb672a Mon Sep 17 00:00:00 2001 From: Hannes Hering Date: Wed, 7 May 2008 14:43:01 +0200 Subject: memory: Introduce exports for memory notifiers This patch introduces two exports to allow modules to use memory notifiers. Signed-off-by: Hannes Hering Signed-off-by: Jeff Garzik --- drivers/base/memory.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 8ce6de5..937e825 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c @@ -53,11 +53,13 @@ int register_memory_notifier(struct notifier_block *nb) { return blocking_notifier_chain_register(&memory_chain, nb); } +EXPORT_SYMBOL(register_memory_notifier); void unregister_memory_notifier(struct notifier_block *nb) { blocking_notifier_chain_unregister(&memory_chain, nb); } +EXPORT_SYMBOL(unregister_memory_notifier); /* * register_memory - Setup a sysfs device for a memory block -- cgit v1.1 From fb7b6ca2b6b7c23b52be143bdd5f55a23b9780c8 Mon Sep 17 00:00:00 2001 From: Hannes Hering Date: Wed, 7 May 2008 14:43:20 +0200 Subject: ehea: Add dependency to Kconfig The new ehea memory hot plug implementation depends on MEMORY_HOTPLUG. Signed-off-by: Hannes Hering Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index d27f54a..9f6cc8a 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2426,7 +2426,7 @@ config CHELSIO_T3 config EHEA tristate "eHEA Ethernet support" - depends on IBMEBUS && INET && SPARSEMEM + depends on IBMEBUS && INET && SPARSEMEM && MEMORY_HOTPLUG select INET_LRO ---help--- This driver supports the IBM pSeries eHEA ethernet adapter. -- cgit v1.1 From 48cfb14f8b89d4d5b3df6c16f08b258686fb12ad Mon Sep 17 00:00:00 2001 From: Hannes Hering Date: Wed, 7 May 2008 14:43:36 +0200 Subject: ehea: Add DLPAR memory remove support The eHEA driver uses the recently modified walk_memory_resource for powerpc functionality to detect the memory layout. It further uses the memory hotplug notifiers to catch memory hotplug events. Signed-off-by: Hannes Hering Signed-off-by: Jeff Garzik --- drivers/net/ehea/ehea.h | 27 +++- drivers/net/ehea/ehea_main.c | 25 ++++ drivers/net/ehea/ehea_qmr.c | 286 +++++++++++++++++++++++++++++++------------ 3 files changed, 254 insertions(+), 84 deletions(-) diff --git a/drivers/net/ehea/ehea.h b/drivers/net/ehea/ehea.h index f5dacce..fe872fb 100644 --- a/drivers/net/ehea/ehea.h +++ b/drivers/net/ehea/ehea.h @@ -40,7 +40,7 @@ #include #define DRV_NAME "ehea" -#define DRV_VERSION "EHEA_0090" +#define DRV_VERSION "EHEA_0091" /* eHEA capability flags */ #define DLPAR_PORT_ADD_REM 1 @@ -118,6 +118,13 @@ #define EHEA_MR_ACC_CTRL 0x00800000 #define EHEA_BUSMAP_START 0x8000000000000000ULL +#define EHEA_INVAL_ADDR 0xFFFFFFFFFFFFFFFFULL +#define EHEA_DIR_INDEX_SHIFT 13 /* 8k Entries in 64k block */ +#define EHEA_TOP_INDEX_SHIFT (EHEA_DIR_INDEX_SHIFT * 2) +#define EHEA_MAP_ENTRIES (1 << EHEA_DIR_INDEX_SHIFT) +#define EHEA_MAP_SIZE (0x10000) /* currently fixed map size */ +#define EHEA_INDEX_MASK (EHEA_MAP_ENTRIES - 1) + #define EHEA_WATCH_DOG_TIMEOUT 10*HZ @@ -192,10 +199,20 @@ struct h_epas { set to 0 if unused */ }; -struct ehea_busmap { - unsigned int entries; /* total number of entries */ - unsigned int valid_sections; /* number of valid sections */ - u64 *vaddr; +/* + * Memory map data structures + */ +struct ehea_dir_bmap +{ + u64 ent[EHEA_MAP_ENTRIES]; +}; +struct ehea_top_bmap +{ + struct ehea_dir_bmap *dir[EHEA_MAP_ENTRIES]; +}; +struct ehea_bmap +{ + struct ehea_top_bmap *top[EHEA_MAP_ENTRIES]; }; struct ehea_qp; diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index f9bc21c..d1b6d4e 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -3503,6 +3504,24 @@ void ehea_crash_handler(void) 0, H_DEREG_BCMC); } +static int ehea_mem_notifier(struct notifier_block *nb, + unsigned long action, void *data) +{ + switch (action) { + case MEM_OFFLINE: + ehea_info("memory has been removed"); + ehea_rereg_mrs(NULL); + break; + default: + break; + } + return NOTIFY_OK; +} + +static struct notifier_block ehea_mem_nb = { + .notifier_call = ehea_mem_notifier, +}; + static int ehea_reboot_notifier(struct notifier_block *nb, unsigned long action, void *unused) { @@ -3581,6 +3600,10 @@ int __init ehea_module_init(void) if (ret) ehea_info("failed registering reboot notifier"); + ret = register_memory_notifier(&ehea_mem_nb); + if (ret) + ehea_info("failed registering memory remove notifier"); + ret = crash_shutdown_register(&ehea_crash_handler); if (ret) ehea_info("failed registering crash handler"); @@ -3604,6 +3627,7 @@ int __init ehea_module_init(void) out3: ibmebus_unregister_driver(&ehea_driver); out2: + unregister_memory_notifier(&ehea_mem_nb); unregister_reboot_notifier(&ehea_reboot_nb); crash_shutdown_unregister(&ehea_crash_handler); out: @@ -3621,6 +3645,7 @@ static void __exit ehea_module_exit(void) ret = crash_shutdown_unregister(&ehea_crash_handler); if (ret) ehea_info("failed unregistering crash handler"); + unregister_memory_notifier(&ehea_mem_nb); kfree(ehea_fw_handles.arr); kfree(ehea_bcmc_regs.arr); ehea_destroy_busmap(); diff --git a/drivers/net/ehea/ehea_qmr.c b/drivers/net/ehea/ehea_qmr.c index d522e90..140f05b 100644 --- a/drivers/net/ehea/ehea_qmr.c +++ b/drivers/net/ehea/ehea_qmr.c @@ -31,8 +31,8 @@ #include "ehea_phyp.h" #include "ehea_qmr.h" +struct ehea_bmap *ehea_bmap = NULL; -struct ehea_busmap ehea_bmap = { 0, 0, NULL }; static void *hw_qpageit_get_inc(struct hw_queue *queue) @@ -559,125 +559,253 @@ int ehea_destroy_qp(struct ehea_qp *qp) return 0; } -int ehea_create_busmap(void) +static inline int ehea_calc_index(unsigned long i, unsigned long s) { - u64 vaddr = EHEA_BUSMAP_START; - unsigned long high_section_index = 0; - int i; + return (i >> s) & EHEA_INDEX_MASK; +} - /* - * Sections are not in ascending order -> Loop over all sections and - * find the highest PFN to compute the required map size. - */ - ehea_bmap.valid_sections = 0; +static inline int ehea_init_top_bmap(struct ehea_top_bmap *ehea_top_bmap, + int dir) +{ + if(!ehea_top_bmap->dir[dir]) { + ehea_top_bmap->dir[dir] = + kzalloc(sizeof(struct ehea_dir_bmap), GFP_KERNEL); + if (!ehea_top_bmap->dir[dir]) + return -ENOMEM; + } + return 0; +} - for (i = 0; i < NR_MEM_SECTIONS; i++) - if (valid_section_nr(i)) - high_section_index = i; +static inline int ehea_init_bmap(struct ehea_bmap *ehea_bmap, int top, int dir) +{ + if(!ehea_bmap->top[top]) { + ehea_bmap->top[top] = + kzalloc(sizeof(struct ehea_top_bmap), GFP_KERNEL); + if (!ehea_bmap->top[top]) + return -ENOMEM; + } + return ehea_init_top_bmap(ehea_bmap->top[top], dir); +} - ehea_bmap.entries = high_section_index + 1; - ehea_bmap.vaddr = vmalloc(ehea_bmap.entries * sizeof(*ehea_bmap.vaddr)); +static int ehea_create_busmap_callback(unsigned long pfn, + unsigned long nr_pages, void *arg) +{ + unsigned long i, mr_len, start_section, end_section; + start_section = (pfn * PAGE_SIZE) / EHEA_SECTSIZE; + end_section = start_section + ((nr_pages * PAGE_SIZE) / EHEA_SECTSIZE); + mr_len = *(unsigned long *)arg; - if (!ehea_bmap.vaddr) + ehea_bmap = kzalloc(sizeof(struct ehea_bmap), GFP_KERNEL); + if (!ehea_bmap) return -ENOMEM; - for (i = 0 ; i < ehea_bmap.entries; i++) { - unsigned long pfn = section_nr_to_pfn(i); + for (i = start_section; i < end_section; i++) { + int ret; + int top, dir, idx; + u64 vaddr; + + top = ehea_calc_index(i, EHEA_TOP_INDEX_SHIFT); + dir = ehea_calc_index(i, EHEA_DIR_INDEX_SHIFT); + + ret = ehea_init_bmap(ehea_bmap, top, dir); + if(ret) + return ret; - if (pfn_valid(pfn)) { - ehea_bmap.vaddr[i] = vaddr; - vaddr += EHEA_SECTSIZE; - ehea_bmap.valid_sections++; - } else - ehea_bmap.vaddr[i] = 0; + idx = i & EHEA_INDEX_MASK; + vaddr = EHEA_BUSMAP_START + mr_len + i * EHEA_SECTSIZE; + + ehea_bmap->top[top]->dir[dir]->ent[idx] = vaddr; } + mr_len += nr_pages * PAGE_SIZE; + *(unsigned long *)arg = mr_len; + return 0; } +static unsigned long ehea_mr_len; + +static DEFINE_MUTEX(ehea_busmap_mutex); + +int ehea_create_busmap(void) +{ + int ret; + mutex_lock(&ehea_busmap_mutex); + ehea_mr_len = 0; + ret = walk_memory_resource(0, 1ULL << MAX_PHYSMEM_BITS, &ehea_mr_len, + ehea_create_busmap_callback); + mutex_unlock(&ehea_busmap_mutex); + return ret; +} + void ehea_destroy_busmap(void) { - vfree(ehea_bmap.vaddr); + int top, dir; + mutex_lock(&ehea_busmap_mutex); + if (!ehea_bmap) + goto out_destroy; + + for (top = 0; top < EHEA_MAP_ENTRIES; top++) { + if (!ehea_bmap->top[top]) + continue; + + for (dir = 0; dir < EHEA_MAP_ENTRIES; dir++) { + if (!ehea_bmap->top[top]->dir[dir]) + continue; + + kfree(ehea_bmap->top[top]->dir[dir]); + } + + kfree(ehea_bmap->top[top]); + } + + kfree(ehea_bmap); + ehea_bmap = NULL; +out_destroy: + mutex_unlock(&ehea_busmap_mutex); } u64 ehea_map_vaddr(void *caddr) { - u64 mapped_addr; - unsigned long index = __pa(caddr) >> SECTION_SIZE_BITS; - - if (likely(index < ehea_bmap.entries)) { - mapped_addr = ehea_bmap.vaddr[index]; - if (likely(mapped_addr)) - mapped_addr |= (((unsigned long)caddr) - & (EHEA_SECTSIZE - 1)); - else - mapped_addr = -1; - } else - mapped_addr = -1; - - if (unlikely(mapped_addr == -1)) - if (!test_and_set_bit(__EHEA_STOP_XFER, &ehea_driver_flags)) - schedule_work(&ehea_rereg_mr_task); - - return mapped_addr; + int top, dir, idx; + unsigned long index, offset; + + if (!ehea_bmap) + return EHEA_INVAL_ADDR; + + index = virt_to_abs(caddr) >> SECTION_SIZE_BITS; + top = (index >> EHEA_TOP_INDEX_SHIFT) & EHEA_INDEX_MASK; + if (!ehea_bmap->top[top]) + return EHEA_INVAL_ADDR; + + dir = (index >> EHEA_DIR_INDEX_SHIFT) & EHEA_INDEX_MASK; + if (!ehea_bmap->top[top]->dir[dir]) + return EHEA_INVAL_ADDR; + + idx = index & EHEA_INDEX_MASK; + if (!ehea_bmap->top[top]->dir[dir]->ent[idx]) + return EHEA_INVAL_ADDR; + + offset = (unsigned long)caddr & (EHEA_SECTSIZE - 1); + return ehea_bmap->top[top]->dir[dir]->ent[idx] | offset; +} + +static inline void *ehea_calc_sectbase(int top, int dir, int idx) +{ + unsigned long ret = idx; + ret |= dir << EHEA_DIR_INDEX_SHIFT; + ret |= top << EHEA_TOP_INDEX_SHIFT; + return abs_to_virt(ret << SECTION_SIZE_BITS); +} + +static u64 ehea_reg_mr_section(int top, int dir, int idx, u64 *pt, + struct ehea_adapter *adapter, + struct ehea_mr *mr) +{ + void *pg; + u64 j, m, hret; + unsigned long k = 0; + u64 pt_abs = virt_to_abs(pt); + + void *sectbase = ehea_calc_sectbase(top, dir, idx); + + for (j = 0; j < (EHEA_PAGES_PER_SECTION / EHEA_MAX_RPAGE); j++) { + + for (m = 0; m < EHEA_MAX_RPAGE; m++) { + pg = sectbase + ((k++) * EHEA_PAGESIZE); + pt[m] = virt_to_abs(pg); + } + hret = ehea_h_register_rpage_mr(adapter->handle, mr->handle, 0, + 0, pt_abs, EHEA_MAX_RPAGE); + + if ((hret != H_SUCCESS) + && (hret != H_PAGE_REGISTERED)) { + ehea_h_free_resource(adapter->handle, mr->handle, + FORCE_FREE); + ehea_error("register_rpage_mr failed"); + return hret; + } + } + return hret; +} + +static u64 ehea_reg_mr_sections(int top, int dir, u64 *pt, + struct ehea_adapter *adapter, + struct ehea_mr *mr) +{ + u64 hret = H_SUCCESS; + int idx; + + for (idx = 0; idx < EHEA_MAP_ENTRIES; idx++) { + if (!ehea_bmap->top[top]->dir[dir]->ent[idx]) + continue; + + hret = ehea_reg_mr_section(top, dir, idx, pt, adapter, mr); + if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) + return hret; + } + return hret; +} + +static u64 ehea_reg_mr_dir_sections(int top, u64 *pt, + struct ehea_adapter *adapter, + struct ehea_mr *mr) +{ + u64 hret = H_SUCCESS; + int dir; + + for (dir = 0; dir < EHEA_MAP_ENTRIES; dir++) { + if (!ehea_bmap->top[top]->dir[dir]) + continue; + + hret = ehea_reg_mr_sections(top, dir, pt, adapter, mr); + if ((hret != H_SUCCESS) && (hret != H_PAGE_REGISTERED)) + return hret; + } + return hret; } int ehea_reg_kernel_mr(struct ehea_adapter *adapter, struct ehea_mr *mr) { int ret; u64 *pt; - void *pg; - u64 hret, pt_abs, i, j, m, mr_len; + u64 hret; u32 acc_ctrl = EHEA_MR_ACC_CTRL; - mr_len = ehea_bmap.valid_sections * EHEA_SECTSIZE; + unsigned long top; - pt = kzalloc(PAGE_SIZE, GFP_KERNEL); + pt = kzalloc(PAGE_SIZE, GFP_KERNEL); if (!pt) { ehea_error("no mem"); ret = -ENOMEM; goto out; } - pt_abs = virt_to_abs(pt); - hret = ehea_h_alloc_resource_mr(adapter->handle, - EHEA_BUSMAP_START, mr_len, - acc_ctrl, adapter->pd, + hret = ehea_h_alloc_resource_mr(adapter->handle, EHEA_BUSMAP_START, + ehea_mr_len, acc_ctrl, adapter->pd, &mr->handle, &mr->lkey); + if (hret != H_SUCCESS) { ehea_error("alloc_resource_mr failed"); ret = -EIO; goto out; } - for (i = 0 ; i < ehea_bmap.entries; i++) - if (ehea_bmap.vaddr[i]) { - void *sectbase = __va(i << SECTION_SIZE_BITS); - unsigned long k = 0; - - for (j = 0; j < (EHEA_PAGES_PER_SECTION / - EHEA_MAX_RPAGE); j++) { - - for (m = 0; m < EHEA_MAX_RPAGE; m++) { - pg = sectbase + ((k++) * EHEA_PAGESIZE); - pt[m] = virt_to_abs(pg); - } - - hret = ehea_h_register_rpage_mr(adapter->handle, - mr->handle, - 0, 0, pt_abs, - EHEA_MAX_RPAGE); - if ((hret != H_SUCCESS) - && (hret != H_PAGE_REGISTERED)) { - ehea_h_free_resource(adapter->handle, - mr->handle, - FORCE_FREE); - ehea_error("register_rpage_mr failed"); - ret = -EIO; - goto out; - } - } - } + if (!ehea_bmap) { + ehea_h_free_resource(adapter->handle, mr->handle, FORCE_FREE); + ehea_error("no busmap available"); + ret = -EIO; + goto out; + } + + for (top = 0; top < EHEA_MAP_ENTRIES; top++) { + if (!ehea_bmap->top[top]) + continue; + + hret = ehea_reg_mr_dir_sections(top, pt, adapter, mr); + if((hret != H_PAGE_REGISTERED) && (hret != H_SUCCESS)) + break; + } if (hret != H_SUCCESS) { ehea_h_free_resource(adapter->handle, mr->handle, FORCE_FREE); -- cgit v1.1 From b9b39b625cf57cd0ea998717598b68963cbec3cb Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 7 May 2008 12:51:12 +0100 Subject: [netdrvr] sfc: Add TSO support The SFC4000 controller does not have hardware support for TSO, and the core GSO code incurs a high cost in allocating and freeing skbs. This TSO implementation uses lightweight packet header structures and is substantially faster. Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/efx.c | 4 +- drivers/net/sfc/ethtool.c | 27 ++ drivers/net/sfc/net_driver.h | 14 + drivers/net/sfc/tx.c | 664 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 708 insertions(+), 1 deletion(-) diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c index 59edcf7..418f2e5 100644 --- a/drivers/net/sfc/efx.c +++ b/drivers/net/sfc/efx.c @@ -1873,6 +1873,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type, tx_queue->queue = i; tx_queue->buffer = NULL; tx_queue->channel = &efx->channel[0]; /* for safety */ + tx_queue->tso_headers_free = NULL; } for (i = 0; i < EFX_MAX_RX_QUEUES; i++) { rx_queue = &efx->rx_queue[i]; @@ -2071,7 +2072,8 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev, net_dev = alloc_etherdev(sizeof(*efx)); if (!net_dev) return -ENOMEM; - net_dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_HIGHDMA; + net_dev->features |= (NETIF_F_IP_CSUM | NETIF_F_SG | + NETIF_F_HIGHDMA | NETIF_F_TSO); if (lro) net_dev->features |= NETIF_F_LRO; efx = net_dev->priv; diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index ad541ba..b756840 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -272,6 +272,22 @@ static void efx_ethtool_get_stats(struct net_device *net_dev, } } +static int efx_ethtool_set_tso(struct net_device *net_dev, u32 enable) +{ + int rc; + + /* Our TSO requires TX checksumming, so force TX checksumming + * on when TSO is enabled. + */ + if (enable) { + rc = efx_ethtool_set_tx_csum(net_dev, 1); + if (rc) + return rc; + } + + return ethtool_op_set_tso(net_dev, enable); +} + static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable) { struct efx_nic *efx = net_dev->priv; @@ -283,6 +299,15 @@ static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable) efx_flush_queues(efx); + /* Our TSO requires TX checksumming, so disable TSO when + * checksumming is disabled + */ + if (!enable) { + rc = efx_ethtool_set_tso(net_dev, 0); + if (rc) + return rc; + } + return 0; } @@ -451,6 +476,8 @@ struct ethtool_ops efx_ethtool_ops = { .set_tx_csum = efx_ethtool_set_tx_csum, .get_sg = ethtool_op_get_sg, .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = efx_ethtool_set_tso, .get_flags = ethtool_op_get_flags, .set_flags = ethtool_op_set_flags, .get_strings = efx_ethtool_get_strings, diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index c505482..6ffa711 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -134,6 +134,8 @@ struct efx_special_buffer { * Set only on the final fragment of a packet; %NULL for all other * fragments. When this fragment completes, then we can free this * skb. + * @tsoh: The associated TSO header structure, or %NULL if this + * buffer is not a TSO header. * @dma_addr: DMA address of the fragment. * @len: Length of this fragment. * This field is zero when the queue slot is empty. @@ -144,6 +146,7 @@ struct efx_special_buffer { */ struct efx_tx_buffer { const struct sk_buff *skb; + struct efx_tso_header *tsoh; dma_addr_t dma_addr; unsigned short len; unsigned char continuation; @@ -187,6 +190,13 @@ struct efx_tx_buffer { * variable indicates that the queue is full. This is to * avoid cache-line ping-pong between the xmit path and the * completion path. + * @tso_headers_free: A list of TSO headers allocated for this TX queue + * that are not in use, and so available for new TSO sends. The list + * is protected by the TX queue lock. + * @tso_bursts: Number of times TSO xmit invoked by kernel + * @tso_long_headers: Number of packets with headers too long for standard + * blocks + * @tso_packets: Number of packets via the TSO xmit path */ struct efx_tx_queue { /* Members which don't change on the fast path */ @@ -206,6 +216,10 @@ struct efx_tx_queue { unsigned int insert_count ____cacheline_aligned_in_smp; unsigned int write_count; unsigned int old_read_count; + struct efx_tso_header *tso_headers_free; + unsigned int tso_bursts; + unsigned int tso_long_headers; + unsigned int tso_packets; }; /** diff --git a/drivers/net/sfc/tx.c b/drivers/net/sfc/tx.c index fbb866b..9b436f5 100644 --- a/drivers/net/sfc/tx.c +++ b/drivers/net/sfc/tx.c @@ -82,6 +82,46 @@ static inline void efx_dequeue_buffer(struct efx_tx_queue *tx_queue, } } +/** + * struct efx_tso_header - a DMA mapped buffer for packet headers + * @next: Linked list of free ones. + * The list is protected by the TX queue lock. + * @dma_unmap_len: Length to unmap for an oversize buffer, or 0. + * @dma_addr: The DMA address of the header below. + * + * This controls the memory used for a TSO header. Use TSOH_DATA() + * to find the packet header data. Use TSOH_SIZE() to calculate the + * total size required for a given packet header length. TSO headers + * in the free list are exactly %TSOH_STD_SIZE bytes in size. + */ +struct efx_tso_header { + union { + struct efx_tso_header *next; + size_t unmap_len; + }; + dma_addr_t dma_addr; +}; + +static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, + const struct sk_buff *skb); +static void efx_fini_tso(struct efx_tx_queue *tx_queue); +static void efx_tsoh_heap_free(struct efx_tx_queue *tx_queue, + struct efx_tso_header *tsoh); + +static inline void efx_tsoh_free(struct efx_tx_queue *tx_queue, + struct efx_tx_buffer *buffer) +{ + if (buffer->tsoh) { + if (likely(!buffer->tsoh->unmap_len)) { + buffer->tsoh->next = tx_queue->tso_headers_free; + tx_queue->tso_headers_free = buffer->tsoh; + } else { + efx_tsoh_heap_free(tx_queue, buffer->tsoh); + } + buffer->tsoh = NULL; + } +} + /* * Add a socket buffer to a TX queue @@ -114,6 +154,9 @@ static inline int efx_enqueue_skb(struct efx_tx_queue *tx_queue, EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count); + if (skb_shinfo((struct sk_buff *)skb)->gso_size) + return efx_enqueue_skb_tso(tx_queue, skb); + /* Get size of the initial fragment */ len = skb_headlen(skb); @@ -166,6 +209,8 @@ static inline int efx_enqueue_skb(struct efx_tx_queue *tx_queue, insert_ptr = (tx_queue->insert_count & efx->type->txd_ring_mask); buffer = &tx_queue->buffer[insert_ptr]; + efx_tsoh_free(tx_queue, buffer); + EFX_BUG_ON_PARANOID(buffer->tsoh); EFX_BUG_ON_PARANOID(buffer->skb); EFX_BUG_ON_PARANOID(buffer->len); EFX_BUG_ON_PARANOID(buffer->continuation != 1); @@ -432,6 +477,9 @@ void efx_fini_tx_queue(struct efx_tx_queue *tx_queue) efx_release_tx_buffers(tx_queue); + /* Free up TSO header cache */ + efx_fini_tso(tx_queue); + /* Release queue's stop on port, if any */ if (tx_queue->stopped) { tx_queue->stopped = 0; @@ -450,3 +498,619 @@ void efx_remove_tx_queue(struct efx_tx_queue *tx_queue) } +/* Efx TCP segmentation acceleration. + * + * Why? Because by doing it here in the driver we can go significantly + * faster than the GSO. + * + * Requires TX checksum offload support. + */ + +/* Number of bytes inserted at the start of a TSO header buffer, + * similar to NET_IP_ALIGN. + */ +#if defined(__i386__) || defined(__x86_64__) +#define TSOH_OFFSET 0 +#else +#define TSOH_OFFSET NET_IP_ALIGN +#endif + +#define TSOH_BUFFER(tsoh) ((u8 *)(tsoh + 1) + TSOH_OFFSET) + +/* Total size of struct efx_tso_header, buffer and padding */ +#define TSOH_SIZE(hdr_len) \ + (sizeof(struct efx_tso_header) + TSOH_OFFSET + hdr_len) + +/* Size of blocks on free list. Larger blocks must be allocated from + * the heap. + */ +#define TSOH_STD_SIZE 128 + +#define PTR_DIFF(p1, p2) ((u8 *)(p1) - (u8 *)(p2)) +#define ETH_HDR_LEN(skb) (skb_network_header(skb) - (skb)->data) +#define SKB_TCP_OFF(skb) PTR_DIFF(tcp_hdr(skb), (skb)->data) +#define SKB_IPV4_OFF(skb) PTR_DIFF(ip_hdr(skb), (skb)->data) + +/** + * struct tso_state - TSO state for an SKB + * @remaining_len: Bytes of data we've yet to segment + * @seqnum: Current sequence number + * @packet_space: Remaining space in current packet + * @ifc: Input fragment cursor. + * Where we are in the current fragment of the incoming SKB. These + * values get updated in place when we split a fragment over + * multiple packets. + * @p: Parameters. + * These values are set once at the start of the TSO send and do + * not get changed as the routine progresses. + * + * The state used during segmentation. It is put into this data structure + * just to make it easy to pass into inline functions. + */ +struct tso_state { + unsigned remaining_len; + unsigned seqnum; + unsigned packet_space; + + struct { + /* DMA address of current position */ + dma_addr_t dma_addr; + /* Remaining length */ + unsigned int len; + /* DMA address and length of the whole fragment */ + unsigned int unmap_len; + dma_addr_t unmap_addr; + struct page *page; + unsigned page_off; + } ifc; + + struct { + /* The number of bytes of header */ + unsigned int header_length; + + /* The number of bytes to put in each outgoing segment. */ + int full_packet_size; + + /* Current IPv4 ID, host endian. */ + unsigned ipv4_id; + } p; +}; + + +/* + * Verify that our various assumptions about sk_buffs and the conditions + * under which TSO will be attempted hold true. + */ +static inline void efx_tso_check_safe(const struct sk_buff *skb) +{ + EFX_BUG_ON_PARANOID(skb->protocol != htons(ETH_P_IP)); + EFX_BUG_ON_PARANOID(((struct ethhdr *)skb->data)->h_proto != + skb->protocol); + EFX_BUG_ON_PARANOID(ip_hdr(skb)->protocol != IPPROTO_TCP); + EFX_BUG_ON_PARANOID((PTR_DIFF(tcp_hdr(skb), skb->data) + + (tcp_hdr(skb)->doff << 2u)) > + skb_headlen(skb)); +} + + +/* + * Allocate a page worth of efx_tso_header structures, and string them + * into the tx_queue->tso_headers_free linked list. Return 0 or -ENOMEM. + */ +static int efx_tsoh_block_alloc(struct efx_tx_queue *tx_queue) +{ + + struct pci_dev *pci_dev = tx_queue->efx->pci_dev; + struct efx_tso_header *tsoh; + dma_addr_t dma_addr; + u8 *base_kva, *kva; + + base_kva = pci_alloc_consistent(pci_dev, PAGE_SIZE, &dma_addr); + if (base_kva == NULL) { + EFX_ERR(tx_queue->efx, "Unable to allocate page for TSO" + " headers\n"); + return -ENOMEM; + } + + /* pci_alloc_consistent() allocates pages. */ + EFX_BUG_ON_PARANOID(dma_addr & (PAGE_SIZE - 1u)); + + for (kva = base_kva; kva < base_kva + PAGE_SIZE; kva += TSOH_STD_SIZE) { + tsoh = (struct efx_tso_header *)kva; + tsoh->dma_addr = dma_addr + (TSOH_BUFFER(tsoh) - base_kva); + tsoh->next = tx_queue->tso_headers_free; + tx_queue->tso_headers_free = tsoh; + } + + return 0; +} + + +/* Free up a TSO header, and all others in the same page. */ +static void efx_tsoh_block_free(struct efx_tx_queue *tx_queue, + struct efx_tso_header *tsoh, + struct pci_dev *pci_dev) +{ + struct efx_tso_header **p; + unsigned long base_kva; + dma_addr_t base_dma; + + base_kva = (unsigned long)tsoh & PAGE_MASK; + base_dma = tsoh->dma_addr & PAGE_MASK; + + p = &tx_queue->tso_headers_free; + while (*p != NULL) + if (((unsigned long)*p & PAGE_MASK) == base_kva) + *p = (*p)->next; + else + p = &(*p)->next; + + pci_free_consistent(pci_dev, PAGE_SIZE, (void *)base_kva, base_dma); +} + +static struct efx_tso_header * +efx_tsoh_heap_alloc(struct efx_tx_queue *tx_queue, size_t header_len) +{ + struct efx_tso_header *tsoh; + + tsoh = kmalloc(TSOH_SIZE(header_len), GFP_ATOMIC | GFP_DMA); + if (unlikely(!tsoh)) + return NULL; + + tsoh->dma_addr = pci_map_single(tx_queue->efx->pci_dev, + TSOH_BUFFER(tsoh), header_len, + PCI_DMA_TODEVICE); + if (unlikely(pci_dma_mapping_error(tsoh->dma_addr))) { + kfree(tsoh); + return NULL; + } + + tsoh->unmap_len = header_len; + return tsoh; +} + +static void +efx_tsoh_heap_free(struct efx_tx_queue *tx_queue, struct efx_tso_header *tsoh) +{ + pci_unmap_single(tx_queue->efx->pci_dev, + tsoh->dma_addr, tsoh->unmap_len, + PCI_DMA_TODEVICE); + kfree(tsoh); +} + +/** + * efx_tx_queue_insert - push descriptors onto the TX queue + * @tx_queue: Efx TX queue + * @dma_addr: DMA address of fragment + * @len: Length of fragment + * @skb: Only non-null for end of last segment + * @end_of_packet: True if last fragment in a packet + * @unmap_addr: DMA address of fragment for unmapping + * @unmap_len: Only set this in last segment of a fragment + * + * Push descriptors onto the TX queue. Return 0 on success or 1 if + * @tx_queue full. + */ +static int efx_tx_queue_insert(struct efx_tx_queue *tx_queue, + dma_addr_t dma_addr, unsigned len, + const struct sk_buff *skb, int end_of_packet, + dma_addr_t unmap_addr, unsigned unmap_len) +{ + struct efx_tx_buffer *buffer; + struct efx_nic *efx = tx_queue->efx; + unsigned dma_len, fill_level, insert_ptr, misalign; + int q_space; + + EFX_BUG_ON_PARANOID(len <= 0); + + fill_level = tx_queue->insert_count - tx_queue->old_read_count; + /* -1 as there is no way to represent all descriptors used */ + q_space = efx->type->txd_ring_mask - 1 - fill_level; + + while (1) { + if (unlikely(q_space-- <= 0)) { + /* It might be that completions have happened + * since the xmit path last checked. Update + * the xmit path's copy of read_count. + */ + ++tx_queue->stopped; + /* This memory barrier protects the change of + * stopped from the access of read_count. */ + smp_mb(); + tx_queue->old_read_count = + *(volatile unsigned *)&tx_queue->read_count; + fill_level = (tx_queue->insert_count + - tx_queue->old_read_count); + q_space = efx->type->txd_ring_mask - 1 - fill_level; + if (unlikely(q_space-- <= 0)) + return 1; + smp_mb(); + --tx_queue->stopped; + } + + insert_ptr = tx_queue->insert_count & efx->type->txd_ring_mask; + buffer = &tx_queue->buffer[insert_ptr]; + ++tx_queue->insert_count; + + EFX_BUG_ON_PARANOID(tx_queue->insert_count - + tx_queue->read_count > + efx->type->txd_ring_mask); + + efx_tsoh_free(tx_queue, buffer); + EFX_BUG_ON_PARANOID(buffer->len); + EFX_BUG_ON_PARANOID(buffer->unmap_len); + EFX_BUG_ON_PARANOID(buffer->skb); + EFX_BUG_ON_PARANOID(buffer->continuation != 1); + EFX_BUG_ON_PARANOID(buffer->tsoh); + + buffer->dma_addr = dma_addr; + + /* Ensure we do not cross a boundary unsupported by H/W */ + dma_len = (~dma_addr & efx->type->tx_dma_mask) + 1; + + misalign = (unsigned)dma_addr & efx->type->bug5391_mask; + if (misalign && dma_len + misalign > 512) + dma_len = 512 - misalign; + + /* If there is enough space to send then do so */ + if (dma_len >= len) + break; + + buffer->len = dma_len; /* Don't set the other members */ + dma_addr += dma_len; + len -= dma_len; + } + + EFX_BUG_ON_PARANOID(!len); + buffer->len = len; + buffer->skb = skb; + buffer->continuation = !end_of_packet; + buffer->unmap_addr = unmap_addr; + buffer->unmap_len = unmap_len; + return 0; +} + + +/* + * Put a TSO header into the TX queue. + * + * This is special-cased because we know that it is small enough to fit in + * a single fragment, and we know it doesn't cross a page boundary. It + * also allows us to not worry about end-of-packet etc. + */ +static inline void efx_tso_put_header(struct efx_tx_queue *tx_queue, + struct efx_tso_header *tsoh, unsigned len) +{ + struct efx_tx_buffer *buffer; + + buffer = &tx_queue->buffer[tx_queue->insert_count & + tx_queue->efx->type->txd_ring_mask]; + efx_tsoh_free(tx_queue, buffer); + EFX_BUG_ON_PARANOID(buffer->len); + EFX_BUG_ON_PARANOID(buffer->unmap_len); + EFX_BUG_ON_PARANOID(buffer->skb); + EFX_BUG_ON_PARANOID(buffer->continuation != 1); + EFX_BUG_ON_PARANOID(buffer->tsoh); + buffer->len = len; + buffer->dma_addr = tsoh->dma_addr; + buffer->tsoh = tsoh; + + ++tx_queue->insert_count; +} + + +/* Remove descriptors put into a tx_queue. */ +static void efx_enqueue_unwind(struct efx_tx_queue *tx_queue) +{ + struct efx_tx_buffer *buffer; + + /* Work backwards until we hit the original insert pointer value */ + while (tx_queue->insert_count != tx_queue->write_count) { + --tx_queue->insert_count; + buffer = &tx_queue->buffer[tx_queue->insert_count & + tx_queue->efx->type->txd_ring_mask]; + efx_tsoh_free(tx_queue, buffer); + EFX_BUG_ON_PARANOID(buffer->skb); + buffer->len = 0; + buffer->continuation = 1; + if (buffer->unmap_len) { + pci_unmap_page(tx_queue->efx->pci_dev, + buffer->unmap_addr, + buffer->unmap_len, PCI_DMA_TODEVICE); + buffer->unmap_len = 0; + } + } +} + + +/* Parse the SKB header and initialise state. */ +static inline void tso_start(struct tso_state *st, const struct sk_buff *skb) +{ + /* All ethernet/IP/TCP headers combined size is TCP header size + * plus offset of TCP header relative to start of packet. + */ + st->p.header_length = ((tcp_hdr(skb)->doff << 2u) + + PTR_DIFF(tcp_hdr(skb), skb->data)); + st->p.full_packet_size = (st->p.header_length + + skb_shinfo(skb)->gso_size); + + st->p.ipv4_id = ntohs(ip_hdr(skb)->id); + st->seqnum = ntohl(tcp_hdr(skb)->seq); + + EFX_BUG_ON_PARANOID(tcp_hdr(skb)->urg); + EFX_BUG_ON_PARANOID(tcp_hdr(skb)->syn); + EFX_BUG_ON_PARANOID(tcp_hdr(skb)->rst); + + st->packet_space = st->p.full_packet_size; + st->remaining_len = skb->len - st->p.header_length; +} + + +/** + * tso_get_fragment - record fragment details and map for DMA + * @st: TSO state + * @efx: Efx NIC + * @data: Pointer to fragment data + * @len: Length of fragment + * + * Record fragment details and map for DMA. Return 0 on success, or + * -%ENOMEM if DMA mapping fails. + */ +static inline int tso_get_fragment(struct tso_state *st, struct efx_nic *efx, + int len, struct page *page, int page_off) +{ + + st->ifc.unmap_addr = pci_map_page(efx->pci_dev, page, page_off, + len, PCI_DMA_TODEVICE); + if (likely(!pci_dma_mapping_error(st->ifc.unmap_addr))) { + st->ifc.unmap_len = len; + st->ifc.len = len; + st->ifc.dma_addr = st->ifc.unmap_addr; + st->ifc.page = page; + st->ifc.page_off = page_off; + return 0; + } + return -ENOMEM; +} + + +/** + * tso_fill_packet_with_fragment - form descriptors for the current fragment + * @tx_queue: Efx TX queue + * @skb: Socket buffer + * @st: TSO state + * + * Form descriptors for the current fragment, until we reach the end + * of fragment or end-of-packet. Return 0 on success, 1 if not enough + * space in @tx_queue. + */ +static inline int tso_fill_packet_with_fragment(struct efx_tx_queue *tx_queue, + const struct sk_buff *skb, + struct tso_state *st) +{ + + int n, end_of_packet, rc; + + if (st->ifc.len == 0) + return 0; + if (st->packet_space == 0) + return 0; + + EFX_BUG_ON_PARANOID(st->ifc.len <= 0); + EFX_BUG_ON_PARANOID(st->packet_space <= 0); + + n = min(st->ifc.len, st->packet_space); + + st->packet_space -= n; + st->remaining_len -= n; + st->ifc.len -= n; + st->ifc.page_off += n; + end_of_packet = st->remaining_len == 0 || st->packet_space == 0; + + rc = efx_tx_queue_insert(tx_queue, st->ifc.dma_addr, n, + st->remaining_len ? NULL : skb, + end_of_packet, st->ifc.unmap_addr, + st->ifc.len ? 0 : st->ifc.unmap_len); + + st->ifc.dma_addr += n; + + return rc; +} + + +/** + * tso_start_new_packet - generate a new header and prepare for the new packet + * @tx_queue: Efx TX queue + * @skb: Socket buffer + * @st: TSO state + * + * Generate a new header and prepare for the new packet. Return 0 on + * success, or -1 if failed to alloc header. + */ +static inline int tso_start_new_packet(struct efx_tx_queue *tx_queue, + const struct sk_buff *skb, + struct tso_state *st) +{ + struct efx_tso_header *tsoh; + struct iphdr *tsoh_iph; + struct tcphdr *tsoh_th; + unsigned ip_length; + u8 *header; + + /* Allocate a DMA-mapped header buffer. */ + if (likely(TSOH_SIZE(st->p.header_length) <= TSOH_STD_SIZE)) { + if (tx_queue->tso_headers_free == NULL) + if (efx_tsoh_block_alloc(tx_queue)) + return -1; + EFX_BUG_ON_PARANOID(!tx_queue->tso_headers_free); + tsoh = tx_queue->tso_headers_free; + tx_queue->tso_headers_free = tsoh->next; + tsoh->unmap_len = 0; + } else { + tx_queue->tso_long_headers++; + tsoh = efx_tsoh_heap_alloc(tx_queue, st->p.header_length); + if (unlikely(!tsoh)) + return -1; + } + + header = TSOH_BUFFER(tsoh); + tsoh_th = (struct tcphdr *)(header + SKB_TCP_OFF(skb)); + tsoh_iph = (struct iphdr *)(header + SKB_IPV4_OFF(skb)); + + /* Copy and update the headers. */ + memcpy(header, skb->data, st->p.header_length); + + tsoh_th->seq = htonl(st->seqnum); + st->seqnum += skb_shinfo(skb)->gso_size; + if (st->remaining_len > skb_shinfo(skb)->gso_size) { + /* This packet will not finish the TSO burst. */ + ip_length = st->p.full_packet_size - ETH_HDR_LEN(skb); + tsoh_th->fin = 0; + tsoh_th->psh = 0; + } else { + /* This packet will be the last in the TSO burst. */ + ip_length = (st->p.header_length - ETH_HDR_LEN(skb) + + st->remaining_len); + tsoh_th->fin = tcp_hdr(skb)->fin; + tsoh_th->psh = tcp_hdr(skb)->psh; + } + tsoh_iph->tot_len = htons(ip_length); + + /* Linux leaves suitable gaps in the IP ID space for us to fill. */ + tsoh_iph->id = htons(st->p.ipv4_id); + st->p.ipv4_id++; + + st->packet_space = skb_shinfo(skb)->gso_size; + ++tx_queue->tso_packets; + + /* Form a descriptor for this header. */ + efx_tso_put_header(tx_queue, tsoh, st->p.header_length); + + return 0; +} + + +/** + * efx_enqueue_skb_tso - segment and transmit a TSO socket buffer + * @tx_queue: Efx TX queue + * @skb: Socket buffer + * + * Context: You must hold netif_tx_lock() to call this function. + * + * Add socket buffer @skb to @tx_queue, doing TSO or return != 0 if + * @skb was not enqueued. In all cases @skb is consumed. Return + * %NETDEV_TX_OK or %NETDEV_TX_BUSY. + */ +static int efx_enqueue_skb_tso(struct efx_tx_queue *tx_queue, + const struct sk_buff *skb) +{ + int frag_i, rc, rc2 = NETDEV_TX_OK; + struct tso_state state; + skb_frag_t *f; + + /* Verify TSO is safe - these checks should never fail. */ + efx_tso_check_safe(skb); + + EFX_BUG_ON_PARANOID(tx_queue->write_count != tx_queue->insert_count); + + tso_start(&state, skb); + + /* Assume that skb header area contains exactly the headers, and + * all payload is in the frag list. + */ + if (skb_headlen(skb) == state.p.header_length) { + /* Grab the first payload fragment. */ + EFX_BUG_ON_PARANOID(skb_shinfo(skb)->nr_frags < 1); + frag_i = 0; + f = &skb_shinfo(skb)->frags[frag_i]; + rc = tso_get_fragment(&state, tx_queue->efx, + f->size, f->page, f->page_offset); + if (rc) + goto mem_err; + } else { + /* It may look like this code fragment assumes that the + * skb->data portion does not cross a page boundary, but + * that is not the case. It is guaranteed to be direct + * mapped memory, and therefore is physically contiguous, + * and so DMA will work fine. kmap_atomic() on this region + * will just return the direct mapping, so that will work + * too. + */ + int page_off = (unsigned long)skb->data & (PAGE_SIZE - 1); + int hl = state.p.header_length; + rc = tso_get_fragment(&state, tx_queue->efx, + skb_headlen(skb) - hl, + virt_to_page(skb->data), page_off + hl); + if (rc) + goto mem_err; + frag_i = -1; + } + + if (tso_start_new_packet(tx_queue, skb, &state) < 0) + goto mem_err; + + while (1) { + rc = tso_fill_packet_with_fragment(tx_queue, skb, &state); + if (unlikely(rc)) + goto stop; + + /* Move onto the next fragment? */ + if (state.ifc.len == 0) { + if (++frag_i >= skb_shinfo(skb)->nr_frags) + /* End of payload reached. */ + break; + f = &skb_shinfo(skb)->frags[frag_i]; + rc = tso_get_fragment(&state, tx_queue->efx, + f->size, f->page, f->page_offset); + if (rc) + goto mem_err; + } + + /* Start at new packet? */ + if (state.packet_space == 0 && + tso_start_new_packet(tx_queue, skb, &state) < 0) + goto mem_err; + } + + /* Pass off to hardware */ + falcon_push_buffers(tx_queue); + + tx_queue->tso_bursts++; + return NETDEV_TX_OK; + + mem_err: + EFX_ERR(tx_queue->efx, "Out of memory for TSO headers, or PCI mapping" + " error\n"); + dev_kfree_skb_any((struct sk_buff *)skb); + goto unwind; + + stop: + rc2 = NETDEV_TX_BUSY; + + /* Stop the queue if it wasn't stopped before. */ + if (tx_queue->stopped == 1) + efx_stop_queue(tx_queue->efx); + + unwind: + efx_enqueue_unwind(tx_queue); + return rc2; +} + + +/* + * Free up all TSO datastructures associated with tx_queue. This + * routine should be called only once the tx_queue is both empty and + * will no longer be used. + */ +static void efx_fini_tso(struct efx_tx_queue *tx_queue) +{ + unsigned i; + + if (tx_queue->buffer) + for (i = 0; i <= tx_queue->efx->type->txd_ring_mask; ++i) + efx_tsoh_free(tx_queue, &tx_queue->buffer[i]); + + while (tx_queue->tso_headers_free != NULL) + efx_tsoh_block_free(tx_queue, tx_queue->tso_headers_free, + tx_queue->efx->pci_dev); +} -- cgit v1.1 From 75f2d3eac93277fa022b2fbe51257e856575e757 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 7 May 2008 12:55:13 +0100 Subject: [netdrvr] sfc: Add phy_flash_cfg module parameter and implementation The 10Xpress PHY supports flash upgrades through MDIO, but needs to be put in upgrade mode at power-up. This adds a module parameter and other logic to support that. Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/boards.h | 2 ++ drivers/net/sfc/falcon_xmac.c | 4 ++++ drivers/net/sfc/sfe4001.c | 14 ++++++++++++++ drivers/net/sfc/tenxpress.c | 10 ++++++---- 4 files changed, 26 insertions(+), 4 deletions(-) diff --git a/drivers/net/sfc/boards.h b/drivers/net/sfc/boards.h index f56341d..695764d 100644 --- a/drivers/net/sfc/boards.h +++ b/drivers/net/sfc/boards.h @@ -22,5 +22,7 @@ enum efx_board_type { extern int efx_set_board_info(struct efx_nic *efx, u16 revision_info); extern int sfe4001_poweron(struct efx_nic *efx); extern void sfe4001_poweroff(struct efx_nic *efx); +/* Are we putting the PHY into flash config mode */ +extern unsigned int sfe4001_phy_flash_cfg; #endif diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index aa7521b..d99efe2 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c @@ -69,6 +69,10 @@ static int falcon_reset_xmac(struct efx_nic *efx) udelay(10); } + /* This often fails when DSP is disabled, ignore it */ + if (sfe4001_phy_flash_cfg != 0) + return 0; + EFX_ERR(efx, "timed out waiting for XMAC core reset\n"); return -ETIMEDOUT; } diff --git a/drivers/net/sfc/sfe4001.c b/drivers/net/sfc/sfe4001.c index 11fa9fb..725d1a5 100644 --- a/drivers/net/sfc/sfe4001.c +++ b/drivers/net/sfc/sfe4001.c @@ -130,6 +130,15 @@ void sfe4001_poweroff(struct efx_nic *efx) (void) efx_i2c_read(i2c, MAX6647, RSL, &in, 1); } +/* The P0_EN_3V3X line on SFE4001 boards (from A2 onward) is connected + * to the FLASH_CFG_1 input on the DSP. We must keep it high at power- + * up to allow writing the flash (done through MDIO from userland). + */ +unsigned int sfe4001_phy_flash_cfg; +module_param_named(phy_flash_cfg, sfe4001_phy_flash_cfg, uint, 0444); +MODULE_PARM_DESC(phy_flash_cfg, + "Force PHY to enter flash configuration mode"); + /* This board uses an I2C expander to provider power to the PHY, which needs to * be turned on before the PHY can be used. * Context: Process context, rtnl lock held @@ -203,6 +212,8 @@ int sfe4001_poweron(struct efx_nic *efx) out = 0xff & ~((1 << P0_EN_1V2_LBN) | (1 << P0_EN_2V5_LBN) | (1 << P0_EN_3V3X_LBN) | (1 << P0_EN_5V_LBN) | (1 << P0_X_TRST_LBN)); + if (sfe4001_phy_flash_cfg) + out |= 1 << P0_EN_3V3X_LBN; rc = efx_i2c_write(i2c, PCA9539, P0_OUT, &out, 1); if (rc) @@ -226,6 +237,9 @@ int sfe4001_poweron(struct efx_nic *efx) if (in & (1 << P1_AFE_PWD_LBN)) goto done; + /* DSP doesn't look powered in flash config mode */ + if (sfe4001_phy_flash_cfg) + goto done; } while (++count < 20); EFX_INFO(efx, "timed out waiting for power\n"); diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index a2e9f79..d8df031 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -199,10 +199,12 @@ static int tenxpress_phy_init(struct efx_nic *efx) tenxpress_set_state(efx, TENXPRESS_STATUS_NORMAL); - rc = mdio_clause45_wait_reset_mmds(efx, - TENXPRESS_REQUIRED_DEVS); - if (rc < 0) - goto fail; + if (!sfe4001_phy_flash_cfg) { + rc = mdio_clause45_wait_reset_mmds(efx, + TENXPRESS_REQUIRED_DEVS); + if (rc < 0) + goto fail; + } rc = mdio_clause45_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0); if (rc < 0) -- cgit v1.1 From ba911a4d16fb2dd562f5595731fc96bc8c4929d7 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 7 May 2008 12:56:57 +0100 Subject: [netdrvr] sfc: Removed bogus 'fall-thru' comments Fall-through is expected outside a switch statement. Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/falcon.c | 2 -- drivers/net/sfc/rx.c | 1 - 2 files changed, 3 deletions(-) diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 46db549..9cac344 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -2468,14 +2468,12 @@ int falcon_probe_nic(struct efx_nic *efx) fail5: falcon_free_buffer(efx, &efx->irq_status); fail4: - /* fall-thru */ fail3: if (nic_data->pci_dev2) { pci_dev_put(nic_data->pci_dev2); nic_data->pci_dev2 = NULL; } fail2: - /* fall-thru */ fail1: kfree(efx->nic_data); return rc; diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index 551299b..9fd1984 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c @@ -736,7 +736,6 @@ void __efx_rx_packet(struct efx_channel *channel, /* Update allocation strategy method */ channel->rx_alloc_level += RX_ALLOC_FACTOR_SKB; - /* fall-thru */ done: efx->net_dev->last_rx = jiffies; } -- cgit v1.1 From 707d982700c4cde83913f23eb6430a5bb435122a Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 7 May 2008 12:57:44 +0100 Subject: [netdrvr] sfc: Remove garbage from comment Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/mdio_10g.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h index 2214b6d..338c62c 100644 --- a/drivers/net/sfc/mdio_10g.h +++ b/drivers/net/sfc/mdio_10g.h @@ -95,7 +95,7 @@ #define MDIO_PMAPMD_CTRL2_10_BT (0xf) #define MDIO_PMAPMD_CTRL2_TYPE_MASK (0xf) -/* /\* PHY XGXS lane state *\/ */ +/* PHY XGXS lane state */ #define MDIO_PHYXS_LANE_STATE (0x18) #define MDIO_PHYXS_LANE_ALIGNED_LBN (12) -- cgit v1.1 From d6742d4a6dfc362b5dbb3e759e6198c3dbb47dbc Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 7 May 2008 12:58:13 +0100 Subject: [netdrvr] sfc: Remove kernel-doc comments for removed members of struct efx_nic Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/net_driver.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 6ffa711..9c285fb 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -667,8 +667,6 @@ union efx_multicast_hash { * @phy_op: PHY interface * @phy_data: PHY private data (including PHY-specific stats) * @mii: PHY interface - * @phy_powered: PHY power state - * @tx_disabled: PHY transmitter turned off * @link_up: Link status * @link_options: Link options (MII/GMII format) * @n_link_state_changes: Number of times the link has changed state -- cgit v1.1 From e52eddaece487b0855f5974ee0a0a3a172043ba8 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 7 May 2008 12:58:41 +0100 Subject: [netdrvr] sfc: Fix code formatting Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/falcon_xmac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index d99efe2..8c41662 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c @@ -32,7 +32,7 @@ (FALCON_XMAC_REGBANK + ((mac_reg) * FALCON_XMAC_REG_SIZE)) void falcon_xmac_writel(struct efx_nic *efx, - efx_dword_t *value, unsigned int mac_reg) + efx_dword_t *value, unsigned int mac_reg) { efx_oword_t temp; @@ -227,7 +227,7 @@ static int falcon_xgmii_status(struct efx_nic *efx) /* The ISR latches, so clear it and re-read */ falcon_xmac_readl(efx, ®, XM_MGT_INT_REG_MAC_B0); falcon_xmac_readl(efx, ®, XM_MGT_INT_REG_MAC_B0); - + if (EFX_DWORD_FIELD(reg, XM_LCLFLT) || EFX_DWORD_FIELD(reg, XM_RMTFLT)) { EFX_INFO(efx, "MGT_INT: "EFX_DWORD_FMT"\n", EFX_DWORD_VAL(reg)); -- cgit v1.1 From 53269e94cdaca6e470c18099912de977a193e815 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 7 May 2008 12:59:10 +0100 Subject: [netdrvr] sfc: Remove unused macro EFX_XAUI_RETRAIN_MAX Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/falcon_xmac.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index 8c41662..b875c7b 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c @@ -495,8 +495,6 @@ void falcon_update_stats_xmac(struct efx_nic *efx) (mac_stats->rx_bytes - mac_stats->rx_good_bytes); } -#define EFX_XAUI_RETRAIN_MAX 8 - int falcon_check_xmac(struct efx_nic *efx) { unsigned xaui_link_ok; -- cgit v1.1 From 05e3ec04460180f48810cddc2f78e80a725657ad Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 7 May 2008 13:00:39 +0100 Subject: [netdrvr] sfc: Increment rx_reset when reported as driver event An RX_RESET event can be reported either as a global or as a driver event. We were counting only global events. Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/falcon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 9cac344..247629c 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1129,6 +1129,7 @@ static void falcon_handle_driver_event(struct efx_channel *channel, case RX_RECOVERY_EV_DECODE: EFX_ERR(efx, "channel %d seen DRIVER RX_RESET event. " "Resetting.\n", channel->channel); + atomic_inc(&efx->rx_reset); efx_schedule_reset(efx, EFX_WORKAROUND_6555(efx) ? RESET_TYPE_RX_RECOVERY : -- cgit v1.1 From 3273c2e8c66a21ae1c53b0c730ee937c6efde7e2 Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 7 May 2008 13:36:19 +0100 Subject: [netdrvr] sfc: sfc: Add self-test support Add a set of self-tests accessible thorugh ethtool. Add hardware loopback and TX disable control code to support them. Signed-off-by: Ben Hutchings Signed-off-by: Jeff Garzik --- drivers/net/sfc/Makefile | 4 +- drivers/net/sfc/enum.h | 49 +++ drivers/net/sfc/ethtool.c | 232 ++++++++++++- drivers/net/sfc/falcon.c | 5 +- drivers/net/sfc/falcon_hwdefs.h | 16 +- drivers/net/sfc/falcon_xmac.c | 72 +++- drivers/net/sfc/mdio_10g.c | 78 +++++ drivers/net/sfc/mdio_10g.h | 22 ++ drivers/net/sfc/net_driver.h | 14 + drivers/net/sfc/rx.c | 10 + drivers/net/sfc/selftest.c | 717 ++++++++++++++++++++++++++++++++++++++++ drivers/net/sfc/selftest.h | 50 +++ drivers/net/sfc/tenxpress.c | 81 +++++ drivers/net/sfc/xfp_phy.c | 36 ++ 14 files changed, 1379 insertions(+), 7 deletions(-) create mode 100644 drivers/net/sfc/selftest.c create mode 100644 drivers/net/sfc/selftest.h diff --git a/drivers/net/sfc/Makefile b/drivers/net/sfc/Makefile index 0f02344..1d2daee 100644 --- a/drivers/net/sfc/Makefile +++ b/drivers/net/sfc/Makefile @@ -1,5 +1,5 @@ sfc-y += efx.o falcon.o tx.o rx.o falcon_xmac.o \ - i2c-direct.o ethtool.o xfp_phy.o mdio_10g.o \ - tenxpress.o boards.o sfe4001.o + i2c-direct.o selftest.o ethtool.o xfp_phy.o \ + mdio_10g.o tenxpress.o boards.o sfe4001.o obj-$(CONFIG_SFC) += sfc.o diff --git a/drivers/net/sfc/enum.h b/drivers/net/sfc/enum.h index 43663a4..c53290d 100644 --- a/drivers/net/sfc/enum.h +++ b/drivers/net/sfc/enum.h @@ -10,6 +10,55 @@ #ifndef EFX_ENUM_H #define EFX_ENUM_H +/** + * enum efx_loopback_mode - loopback modes + * @LOOPBACK_NONE: no loopback + * @LOOPBACK_XGMII: loopback within MAC at XGMII level + * @LOOPBACK_XGXS: loopback within MAC at XGXS level + * @LOOPBACK_XAUI: loopback within MAC at XAUI level + * @LOOPBACK_PHYXS: loopback within PHY at PHYXS level + * @LOOPBACK_PCS: loopback within PHY at PCS level + * @LOOPBACK_PMAPMD: loopback within PHY at PMAPMD level + * @LOOPBACK_NETWORK: reflecting loopback (even further than furthest!) + */ +/* Please keep in order and up-to-date w.r.t the following two #defines */ +enum efx_loopback_mode { + LOOPBACK_NONE = 0, + LOOPBACK_MAC = 1, + LOOPBACK_XGMII = 2, + LOOPBACK_XGXS = 3, + LOOPBACK_XAUI = 4, + LOOPBACK_PHY = 5, + LOOPBACK_PHYXS = 6, + LOOPBACK_PCS = 7, + LOOPBACK_PMAPMD = 8, + LOOPBACK_NETWORK = 9, + LOOPBACK_MAX +}; + +#define LOOPBACK_TEST_MAX LOOPBACK_PMAPMD + +extern const char *efx_loopback_mode_names[]; +#define LOOPBACK_MODE_NAME(mode) \ + STRING_TABLE_LOOKUP(mode, efx_loopback_mode) +#define LOOPBACK_MODE(efx) \ + LOOPBACK_MODE_NAME(efx->loopback_mode) + +/* These loopbacks occur within the controller */ +#define LOOPBACKS_10G_INTERNAL ((1 << LOOPBACK_XGMII)| \ + (1 << LOOPBACK_XGXS) | \ + (1 << LOOPBACK_XAUI)) + +#define LOOPBACK_MASK(_efx) \ + (1 << (_efx)->loopback_mode) + +#define LOOPBACK_INTERNAL(_efx) \ + ((LOOPBACKS_10G_INTERNAL & LOOPBACK_MASK(_efx)) ? 1 : 0) + +#define LOOPBACK_OUT_OF(_from, _to, _mask) \ + (((LOOPBACK_MASK(_from) & (_mask)) && \ + ((LOOPBACK_MASK(_to) & (_mask)) == 0)) ? 1 : 0) + /*****************************************************************************/ /** diff --git a/drivers/net/sfc/ethtool.c b/drivers/net/sfc/ethtool.c index b756840..e2c75d1 100644 --- a/drivers/net/sfc/ethtool.c +++ b/drivers/net/sfc/ethtool.c @@ -12,12 +12,26 @@ #include #include #include "net_driver.h" +#include "selftest.h" #include "efx.h" #include "ethtool.h" #include "falcon.h" #include "gmii.h" #include "mac.h" +const char *efx_loopback_mode_names[] = { + [LOOPBACK_NONE] = "NONE", + [LOOPBACK_MAC] = "MAC", + [LOOPBACK_XGMII] = "XGMII", + [LOOPBACK_XGXS] = "XGXS", + [LOOPBACK_XAUI] = "XAUI", + [LOOPBACK_PHY] = "PHY", + [LOOPBACK_PHYXS] = "PHY(XS)", + [LOOPBACK_PCS] = "PHY(PCS)", + [LOOPBACK_PMAPMD] = "PHY(PMAPMD)", + [LOOPBACK_NETWORK] = "NETWORK", +}; + static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable); struct ethtool_string { @@ -217,23 +231,179 @@ static void efx_ethtool_get_drvinfo(struct net_device *net_dev, strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info)); } +/** + * efx_fill_test - fill in an individual self-test entry + * @test_index: Index of the test + * @strings: Ethtool strings, or %NULL + * @data: Ethtool test results, or %NULL + * @test: Pointer to test result (used only if data != %NULL) + * @unit_format: Unit name format (e.g. "channel\%d") + * @unit_id: Unit id (e.g. 0 for "channel0") + * @test_format: Test name format (e.g. "loopback.\%s.tx.sent") + * @test_id: Test id (e.g. "PHY" for "loopback.PHY.tx_sent") + * + * Fill in an individual self-test entry. + */ +static void efx_fill_test(unsigned int test_index, + struct ethtool_string *strings, u64 *data, + int *test, const char *unit_format, int unit_id, + const char *test_format, const char *test_id) +{ + struct ethtool_string unit_str, test_str; + + /* Fill data value, if applicable */ + if (data) + data[test_index] = *test; + + /* Fill string, if applicable */ + if (strings) { + snprintf(unit_str.name, sizeof(unit_str.name), + unit_format, unit_id); + snprintf(test_str.name, sizeof(test_str.name), + test_format, test_id); + snprintf(strings[test_index].name, + sizeof(strings[test_index].name), + "%-9s%-17s", unit_str.name, test_str.name); + } +} + +#define EFX_PORT_NAME "port%d", 0 +#define EFX_CHANNEL_NAME(_channel) "channel%d", _channel->channel +#define EFX_TX_QUEUE_NAME(_tx_queue) "txq%d", _tx_queue->queue +#define EFX_RX_QUEUE_NAME(_rx_queue) "rxq%d", _rx_queue->queue +#define EFX_LOOPBACK_NAME(_mode, _counter) \ + "loopback.%s." _counter, LOOPBACK_MODE_NAME(mode) + +/** + * efx_fill_loopback_test - fill in a block of loopback self-test entries + * @efx: Efx NIC + * @lb_tests: Efx loopback self-test results structure + * @mode: Loopback test mode + * @test_index: Starting index of the test + * @strings: Ethtool strings, or %NULL + * @data: Ethtool test results, or %NULL + */ +static int efx_fill_loopback_test(struct efx_nic *efx, + struct efx_loopback_self_tests *lb_tests, + enum efx_loopback_mode mode, + unsigned int test_index, + struct ethtool_string *strings, u64 *data) +{ + struct efx_tx_queue *tx_queue; + + efx_for_each_tx_queue(tx_queue, efx) { + efx_fill_test(test_index++, strings, data, + &lb_tests->tx_sent[tx_queue->queue], + EFX_TX_QUEUE_NAME(tx_queue), + EFX_LOOPBACK_NAME(mode, "tx_sent")); + efx_fill_test(test_index++, strings, data, + &lb_tests->tx_done[tx_queue->queue], + EFX_TX_QUEUE_NAME(tx_queue), + EFX_LOOPBACK_NAME(mode, "tx_done")); + } + efx_fill_test(test_index++, strings, data, + &lb_tests->rx_good, + EFX_PORT_NAME, + EFX_LOOPBACK_NAME(mode, "rx_good")); + efx_fill_test(test_index++, strings, data, + &lb_tests->rx_bad, + EFX_PORT_NAME, + EFX_LOOPBACK_NAME(mode, "rx_bad")); + + return test_index; +} + +/** + * efx_ethtool_fill_self_tests - get self-test details + * @efx: Efx NIC + * @tests: Efx self-test results structure, or %NULL + * @strings: Ethtool strings, or %NULL + * @data: Ethtool test results, or %NULL + */ +static int efx_ethtool_fill_self_tests(struct efx_nic *efx, + struct efx_self_tests *tests, + struct ethtool_string *strings, + u64 *data) +{ + struct efx_channel *channel; + unsigned int n = 0; + enum efx_loopback_mode mode; + + /* Interrupt */ + efx_fill_test(n++, strings, data, &tests->interrupt, + "core", 0, "interrupt", NULL); + + /* Event queues */ + efx_for_each_channel(channel, efx) { + efx_fill_test(n++, strings, data, + &tests->eventq_dma[channel->channel], + EFX_CHANNEL_NAME(channel), + "eventq.dma", NULL); + efx_fill_test(n++, strings, data, + &tests->eventq_int[channel->channel], + EFX_CHANNEL_NAME(channel), + "eventq.int", NULL); + efx_fill_test(n++, strings, data, + &tests->eventq_poll[channel->channel], + EFX_CHANNEL_NAME(channel), + "eventq.poll", NULL); + } + + /* PHY presence */ + efx_fill_test(n++, strings, data, &tests->phy_ok, + EFX_PORT_NAME, "phy_ok", NULL); + + /* Loopback tests */ + efx_fill_test(n++, strings, data, &tests->loopback_speed, + EFX_PORT_NAME, "loopback.speed", NULL); + efx_fill_test(n++, strings, data, &tests->loopback_full_duplex, + EFX_PORT_NAME, "loopback.full_duplex", NULL); + for (mode = LOOPBACK_NONE; mode < LOOPBACK_TEST_MAX; mode++) { + if (!(efx->loopback_modes & (1 << mode))) + continue; + n = efx_fill_loopback_test(efx, + &tests->loopback[mode], mode, n, + strings, data); + } + + return n; +} + static int efx_ethtool_get_stats_count(struct net_device *net_dev) { return EFX_ETHTOOL_NUM_STATS; } +static int efx_ethtool_self_test_count(struct net_device *net_dev) +{ + struct efx_nic *efx = net_dev->priv; + + return efx_ethtool_fill_self_tests(efx, NULL, NULL, NULL); +} + static void efx_ethtool_get_strings(struct net_device *net_dev, u32 string_set, u8 *strings) { + struct efx_nic *efx = net_dev->priv; struct ethtool_string *ethtool_strings = (struct ethtool_string *)strings; int i; - if (string_set == ETH_SS_STATS) + switch (string_set) { + case ETH_SS_STATS: for (i = 0; i < EFX_ETHTOOL_NUM_STATS; i++) strncpy(ethtool_strings[i].name, efx_ethtool_stats[i].name, sizeof(ethtool_strings[i].name)); + break; + case ETH_SS_TEST: + efx_ethtool_fill_self_tests(efx, NULL, + ethtool_strings, NULL); + break; + default: + /* No other string sets */ + break; + } } static void efx_ethtool_get_stats(struct net_device *net_dev, @@ -330,6 +500,64 @@ static u32 efx_ethtool_get_rx_csum(struct net_device *net_dev) return efx->rx_checksum_enabled; } +static void efx_ethtool_self_test(struct net_device *net_dev, + struct ethtool_test *test, u64 *data) +{ + struct efx_nic *efx = net_dev->priv; + struct efx_self_tests efx_tests; + int offline, already_up; + int rc; + + ASSERT_RTNL(); + if (efx->state != STATE_RUNNING) { + rc = -EIO; + goto fail1; + } + + /* We need rx buffers and interrupts. */ + already_up = (efx->net_dev->flags & IFF_UP); + if (!already_up) { + rc = dev_open(efx->net_dev); + if (rc) { + EFX_ERR(efx, "failed opening device.\n"); + goto fail2; + } + } + + memset(&efx_tests, 0, sizeof(efx_tests)); + offline = (test->flags & ETH_TEST_FL_OFFLINE); + + /* Perform online self tests first */ + rc = efx_online_test(efx, &efx_tests); + if (rc) + goto out; + + /* Perform offline tests only if online tests passed */ + if (offline) { + /* Stop the kernel from sending packets during the test. */ + efx_stop_queue(efx); + rc = efx_flush_queues(efx); + if (!rc) + rc = efx_offline_test(efx, &efx_tests, + efx->loopback_modes); + efx_wake_queue(efx); + } + + out: + if (!already_up) + dev_close(efx->net_dev); + + EFX_LOG(efx, "%s all %sline self-tests\n", + rc == 0 ? "passed" : "failed", offline ? "off" : "on"); + + fail2: + fail1: + /* Fill ethtool results structures */ + efx_ethtool_fill_self_tests(efx, &efx_tests, NULL, data); + if (rc) + test->flags |= ETH_TEST_FL_FAILED; +} + /* Restart autonegotiation */ static int efx_ethtool_nway_reset(struct net_device *net_dev) { @@ -480,6 +708,8 @@ struct ethtool_ops efx_ethtool_ops = { .set_tso = efx_ethtool_set_tso, .get_flags = ethtool_op_get_flags, .set_flags = ethtool_op_set_flags, + .self_test_count = efx_ethtool_self_test_count, + .self_test = efx_ethtool_self_test, .get_strings = efx_ethtool_get_strings, .phys_id = efx_ethtool_phys_id, .get_stats_count = efx_ethtool_get_stats_count, diff --git a/drivers/net/sfc/falcon.c b/drivers/net/sfc/falcon.c index 247629c..b57cc68 100644 --- a/drivers/net/sfc/falcon.c +++ b/drivers/net/sfc/falcon.c @@ -1732,7 +1732,8 @@ void falcon_drain_tx_fifo(struct efx_nic *efx) efx_oword_t temp; int count; - if (FALCON_REV(efx) < FALCON_REV_B0) + if ((FALCON_REV(efx) < FALCON_REV_B0) || + (efx->loopback_mode != LOOPBACK_NONE)) return; falcon_read(efx, &temp, MAC0_CTRL_REG_KER); @@ -2092,6 +2093,8 @@ static int falcon_probe_phy(struct efx_nic *efx) efx->phy_type); return -1; } + + efx->loopback_modes = LOOPBACKS_10G_INTERNAL | efx->phy_op->loopbacks; return 0; } diff --git a/drivers/net/sfc/falcon_hwdefs.h b/drivers/net/sfc/falcon_hwdefs.h index 0485a63..06e2d68 100644 --- a/drivers/net/sfc/falcon_hwdefs.h +++ b/drivers/net/sfc/falcon_hwdefs.h @@ -636,6 +636,14 @@ #define XX_HIDRVA_WIDTH 1 #define XX_LODRVA_LBN 8 #define XX_LODRVA_WIDTH 1 +#define XX_LPBKD_LBN 3 +#define XX_LPBKD_WIDTH 1 +#define XX_LPBKC_LBN 2 +#define XX_LPBKC_WIDTH 1 +#define XX_LPBKB_LBN 1 +#define XX_LPBKB_WIDTH 1 +#define XX_LPBKA_LBN 0 +#define XX_LPBKA_WIDTH 1 #define XX_TXDRV_CTL_REG_MAC 0x12 #define XX_DEQD_LBN 28 @@ -656,8 +664,14 @@ #define XX_DTXA_WIDTH 4 /* XAUI XGXS core status register */ -#define XX_FORCE_SIG_DECODE_FORCED 0xff #define XX_CORE_STAT_REG_MAC 0x16 +#define XX_FORCE_SIG_LBN 24 +#define XX_FORCE_SIG_WIDTH 8 +#define XX_FORCE_SIG_DECODE_FORCED 0xff +#define XX_XGXS_LB_EN_LBN 23 +#define XX_XGXS_LB_EN_WIDTH 1 +#define XX_XGMII_LB_EN_LBN 22 +#define XX_XGMII_LB_EN_WIDTH 1 #define XX_ALIGN_DONE_LBN 20 #define XX_ALIGN_DONE_WIDTH 1 #define XX_SYNC_STAT_LBN 16 diff --git a/drivers/net/sfc/falcon_xmac.c b/drivers/net/sfc/falcon_xmac.c index b875c7b..a74b793 100644 --- a/drivers/net/sfc/falcon_xmac.c +++ b/drivers/net/sfc/falcon_xmac.c @@ -241,7 +241,7 @@ static void falcon_mask_status_intr(struct efx_nic *efx, int enable) { efx_dword_t reg; - if (FALCON_REV(efx) < FALCON_REV_B0) + if ((FALCON_REV(efx) < FALCON_REV_B0) || LOOPBACK_INTERNAL(efx)) return; /* Flush the ISR */ @@ -288,6 +288,9 @@ int falcon_xaui_link_ok(struct efx_nic *efx) efx_dword_t reg; int align_done, sync_status, link_ok = 0; + if (LOOPBACK_INTERNAL(efx)) + return 1; + /* Read link status */ falcon_xmac_readl(efx, ®, XX_CORE_STAT_REG_MAC); @@ -378,6 +381,61 @@ static void falcon_reconfigure_xmac_core(struct efx_nic *efx) falcon_xmac_writel(efx, ®, XM_ADR_HI_REG_MAC); } +static void falcon_reconfigure_xgxs_core(struct efx_nic *efx) +{ + efx_dword_t reg; + int xgxs_loopback = (efx->loopback_mode == LOOPBACK_XGXS) ? 1 : 0; + int xaui_loopback = (efx->loopback_mode == LOOPBACK_XAUI) ? 1 : 0; + int xgmii_loopback = + (efx->loopback_mode == LOOPBACK_XGMII) ? 1 : 0; + + /* XGXS block is flaky and will need to be reset if moving + * into our out of XGMII, XGXS or XAUI loopbacks. */ + if (EFX_WORKAROUND_5147(efx)) { + int old_xgmii_loopback, old_xgxs_loopback, old_xaui_loopback; + int reset_xgxs; + + falcon_xmac_readl(efx, ®, XX_CORE_STAT_REG_MAC); + old_xgxs_loopback = EFX_DWORD_FIELD(reg, XX_XGXS_LB_EN); + old_xgmii_loopback = EFX_DWORD_FIELD(reg, XX_XGMII_LB_EN); + + falcon_xmac_readl(efx, ®, XX_SD_CTL_REG_MAC); + old_xaui_loopback = EFX_DWORD_FIELD(reg, XX_LPBKA); + + /* The PHY driver may have turned XAUI off */ + reset_xgxs = ((xgxs_loopback != old_xgxs_loopback) || + (xaui_loopback != old_xaui_loopback) || + (xgmii_loopback != old_xgmii_loopback)); + if (reset_xgxs) { + falcon_xmac_readl(efx, ®, XX_PWR_RST_REG_MAC); + EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 1); + EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 1); + falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC); + udelay(1); + EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSTX_EN, 0); + EFX_SET_DWORD_FIELD(reg, XX_RSTXGXSRX_EN, 0); + falcon_xmac_writel(efx, ®, XX_PWR_RST_REG_MAC); + udelay(1); + } + } + + falcon_xmac_readl(efx, ®, XX_CORE_STAT_REG_MAC); + EFX_SET_DWORD_FIELD(reg, XX_FORCE_SIG, + (xgxs_loopback || xaui_loopback) ? + XX_FORCE_SIG_DECODE_FORCED : 0); + EFX_SET_DWORD_FIELD(reg, XX_XGXS_LB_EN, xgxs_loopback); + EFX_SET_DWORD_FIELD(reg, XX_XGMII_LB_EN, xgmii_loopback); + falcon_xmac_writel(efx, ®, XX_CORE_STAT_REG_MAC); + + falcon_xmac_readl(efx, ®, XX_SD_CTL_REG_MAC); + EFX_SET_DWORD_FIELD(reg, XX_LPBKD, xaui_loopback); + EFX_SET_DWORD_FIELD(reg, XX_LPBKC, xaui_loopback); + EFX_SET_DWORD_FIELD(reg, XX_LPBKB, xaui_loopback); + EFX_SET_DWORD_FIELD(reg, XX_LPBKA, xaui_loopback); + falcon_xmac_writel(efx, ®, XX_SD_CTL_REG_MAC); +} + + /* Try and bring the Falcon side of the Falcon-Phy XAUI link fails * to come back up. Bash it until it comes back up */ static int falcon_check_xaui_link_up(struct efx_nic *efx) @@ -386,7 +444,8 @@ static int falcon_check_xaui_link_up(struct efx_nic *efx) tries = EFX_WORKAROUND_5147(efx) ? 5 : 1; max_tries = tries; - if (efx->phy_type == PHY_TYPE_NONE) + if ((efx->loopback_mode == LOOPBACK_NETWORK) || + (efx->phy_type == PHY_TYPE_NONE)) return 0; while (tries) { @@ -412,8 +471,13 @@ void falcon_reconfigure_xmac(struct efx_nic *efx) falcon_mask_status_intr(efx, 0); falcon_deconfigure_mac_wrapper(efx); + + efx->tx_disabled = LOOPBACK_INTERNAL(efx); efx->phy_op->reconfigure(efx); + + falcon_reconfigure_xgxs_core(efx); falcon_reconfigure_xmac_core(efx); + falcon_reconfigure_mac_wrapper(efx); /* Ensure XAUI link is up */ @@ -500,6 +564,10 @@ int falcon_check_xmac(struct efx_nic *efx) unsigned xaui_link_ok; int rc; + if ((efx->loopback_mode == LOOPBACK_NETWORK) || + (efx->phy_type == PHY_TYPE_NONE)) + return 0; + falcon_mask_status_intr(efx, 0); xaui_link_ok = falcon_xaui_link_ok(efx); diff --git a/drivers/net/sfc/mdio_10g.c b/drivers/net/sfc/mdio_10g.c index dc06bb0..c4f540e 100644 --- a/drivers/net/sfc/mdio_10g.c +++ b/drivers/net/sfc/mdio_10g.c @@ -44,6 +44,9 @@ static int mdio_clause45_check_mmd(struct efx_nic *efx, int mmd, int status; int phy_id = efx->mii.phy_id; + if (LOOPBACK_INTERNAL(efx)) + return 0; + /* Read MMD STATUS2 to check it is responding. */ status = mdio_clause45_read(efx, phy_id, mmd, MDIO_MMDREG_STAT2); if (((status >> MDIO_MMDREG_STAT2_PRESENT_LBN) & @@ -164,6 +167,22 @@ int mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) int mmd = 0; int good; + /* If the port is in loopback, then we should only consider a subset + * of mmd's */ + if (LOOPBACK_INTERNAL(efx)) + return 1; + else if (efx->loopback_mode == LOOPBACK_NETWORK) + return 0; + else if (efx->loopback_mode == LOOPBACK_PHYXS) + mmd_mask &= ~(MDIO_MMDREG_DEVS0_PHYXS | + MDIO_MMDREG_DEVS0_PCS | + MDIO_MMDREG_DEVS0_PMAPMD); + else if (efx->loopback_mode == LOOPBACK_PCS) + mmd_mask &= ~(MDIO_MMDREG_DEVS0_PCS | + MDIO_MMDREG_DEVS0_PMAPMD); + else if (efx->loopback_mode == LOOPBACK_PMAPMD) + mmd_mask &= ~MDIO_MMDREG_DEVS0_PMAPMD; + while (mmd_mask) { if (mmd_mask & 1) { /* Double reads because link state is latched, and a @@ -182,6 +201,65 @@ int mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask) return ok; } +void mdio_clause45_transmit_disable(struct efx_nic *efx) +{ + int phy_id = efx->mii.phy_id; + int ctrl1, ctrl2; + + ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, + MDIO_MMDREG_TXDIS); + if (efx->tx_disabled) + ctrl2 |= (1 << MDIO_MMDREG_TXDIS_GLOBAL_LBN); + else + ctrl1 &= ~(1 << MDIO_MMDREG_TXDIS_GLOBAL_LBN); + if (ctrl1 != ctrl2) + mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, + MDIO_MMDREG_TXDIS, ctrl2); +} + +void mdio_clause45_phy_reconfigure(struct efx_nic *efx) +{ + int phy_id = efx->mii.phy_id; + int ctrl1, ctrl2; + + /* Handle (with debouncing) PMA/PMD loopback */ + ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PMAPMD, + MDIO_MMDREG_CTRL1); + + if (efx->loopback_mode == LOOPBACK_PMAPMD) + ctrl2 |= (1 << MDIO_PMAPMD_CTRL1_LBACK_LBN); + else + ctrl2 &= ~(1 << MDIO_PMAPMD_CTRL1_LBACK_LBN); + + if (ctrl1 != ctrl2) + mdio_clause45_write(efx, phy_id, MDIO_MMD_PMAPMD, + MDIO_MMDREG_CTRL1, ctrl2); + + /* Handle (with debouncing) PCS loopback */ + ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PCS, + MDIO_MMDREG_CTRL1); + if (efx->loopback_mode == LOOPBACK_PCS) + ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LBACK_LBN); + else + ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LBACK_LBN); + + if (ctrl1 != ctrl2) + mdio_clause45_write(efx, phy_id, MDIO_MMD_PCS, + MDIO_MMDREG_CTRL1, ctrl2); + + /* Handle (with debouncing) PHYXS network loopback */ + ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS, + MDIO_MMDREG_CTRL1); + if (efx->loopback_mode == LOOPBACK_NETWORK) + ctrl2 |= (1 << MDIO_MMDREG_CTRL1_LBACK_LBN); + else + ctrl2 &= ~(1 << MDIO_MMDREG_CTRL1_LBACK_LBN); + + if (ctrl1 != ctrl2) + mdio_clause45_write(efx, phy_id, MDIO_MMD_PHYXS, + MDIO_MMDREG_CTRL1, ctrl2); +} + /** * mdio_clause45_get_settings - Read (some of) the PHY settings over MDIO. * @efx: Efx NIC diff --git a/drivers/net/sfc/mdio_10g.h b/drivers/net/sfc/mdio_10g.h index 338c62c..cb99f3f 100644 --- a/drivers/net/sfc/mdio_10g.h +++ b/drivers/net/sfc/mdio_10g.h @@ -44,11 +44,16 @@ #define MDIO_MMDREG_DEVS1 (6) #define MDIO_MMDREG_CTRL2 (7) #define MDIO_MMDREG_STAT2 (8) +#define MDIO_MMDREG_TXDIS (9) /* Bits in MMDREG_CTRL1 */ /* Reset */ #define MDIO_MMDREG_CTRL1_RESET_LBN (15) #define MDIO_MMDREG_CTRL1_RESET_WIDTH (1) +/* Loopback */ +/* Loopback bit for WIS, PCS, PHYSX and DTEXS */ +#define MDIO_MMDREG_CTRL1_LBACK_LBN (14) +#define MDIO_MMDREG_CTRL1_LBACK_WIDTH (1) /* Bits in MMDREG_STAT1 */ #define MDIO_MMDREG_STAT1_FAULT_LBN (7) @@ -56,6 +61,9 @@ /* Link state */ #define MDIO_MMDREG_STAT1_LINK_LBN (2) #define MDIO_MMDREG_STAT1_LINK_WIDTH (1) +/* Low power ability */ +#define MDIO_MMDREG_STAT1_LPABLE_LBN (1) +#define MDIO_MMDREG_STAT1_LPABLE_WIDTH (1) /* Bits in ID reg */ #define MDIO_ID_REV(_id32) (_id32 & 0xf) @@ -76,6 +84,14 @@ #define MDIO_MMDREG_STAT2_PRESENT_LBN (14) #define MDIO_MMDREG_STAT2_PRESENT_WIDTH (2) +/* Bits in MMDREG_TXDIS */ +#define MDIO_MMDREG_TXDIS_GLOBAL_LBN (0) +#define MDIO_MMDREG_TXDIS_GLOBAL_WIDTH (1) + +/* MMD-specific bits, ordered by MMD, then register */ +#define MDIO_PMAPMD_CTRL1_LBACK_LBN (0) +#define MDIO_PMAPMD_CTRL1_LBACK_WIDTH (1) + /* PMA type (4 bits) */ #define MDIO_PMAPMD_CTRL2_10G_CX4 (0x0) #define MDIO_PMAPMD_CTRL2_10G_EW (0x1) @@ -217,6 +233,12 @@ int mdio_clause45_check_mmds(struct efx_nic *efx, extern int mdio_clause45_links_ok(struct efx_nic *efx, unsigned int mmd_mask); +/* Generic transmit disable support though PMAPMD */ +extern void mdio_clause45_transmit_disable(struct efx_nic *efx); + +/* Generic part of reconfigure: set/clear loopback bits */ +extern void mdio_clause45_phy_reconfigure(struct efx_nic *efx); + /* Read (some of) the PHY settings over MDIO */ extern void mdio_clause45_get_settings(struct efx_nic *efx, struct ethtool_cmd *ecmd); diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h index 9c285fb..59f261b 100644 --- a/drivers/net/sfc/net_driver.h +++ b/drivers/net/sfc/net_driver.h @@ -448,6 +448,9 @@ struct efx_board { struct efx_blinker blinker; }; +#define STRING_TABLE_LOOKUP(val, member) \ + member ## _names[val] + enum efx_int_mode { /* Be careful if altering to correct macro below */ EFX_INT_MODE_MSIX = 0, @@ -520,6 +523,7 @@ enum efx_fc_type { * @check_hw: Check hardware * @reset_xaui: Reset XAUI side of PHY for (software sequenced reset) * @mmds: MMD presence mask + * @loopbacks: Supported loopback modes mask */ struct efx_phy_operations { int (*init) (struct efx_nic *efx); @@ -529,6 +533,7 @@ struct efx_phy_operations { int (*check_hw) (struct efx_nic *efx); void (*reset_xaui) (struct efx_nic *efx); int mmds; + unsigned loopbacks; }; /* @@ -667,6 +672,7 @@ union efx_multicast_hash { * @phy_op: PHY interface * @phy_data: PHY private data (including PHY-specific stats) * @mii: PHY interface + * @tx_disabled: PHY transmitter turned off * @link_up: Link status * @link_options: Link options (MII/GMII format) * @n_link_state_changes: Number of times the link has changed state @@ -674,6 +680,9 @@ union efx_multicast_hash { * @multicast_hash: Multicast hash table * @flow_control: Flow control flags - separate RX/TX so can't use link_options * @reconfigure_work: work item for dealing with PHY events + * @loopback_mode: Loopback status + * @loopback_modes: Supported loopback mode bitmask + * @loopback_selftest: Offline self-test private state * * The @priv field of the corresponding &struct net_device points to * this. @@ -733,6 +742,7 @@ struct efx_nic { struct efx_phy_operations *phy_op; void *phy_data; struct mii_if_info mii; + unsigned tx_disabled; int link_up; unsigned int link_options; @@ -744,6 +754,10 @@ struct efx_nic { struct work_struct reconfigure_work; atomic_t rx_reset; + enum efx_loopback_mode loopback_mode; + unsigned int loopback_modes; + + void *loopback_selftest; }; /** diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c index 9fd1984..6706223 100644 --- a/drivers/net/sfc/rx.c +++ b/drivers/net/sfc/rx.c @@ -19,6 +19,7 @@ #include "rx.h" #include "efx.h" #include "falcon.h" +#include "selftest.h" #include "workarounds.h" /* Number of RX descriptors pushed at once. */ @@ -683,6 +684,15 @@ void __efx_rx_packet(struct efx_channel *channel, struct sk_buff *skb; int lro = efx->net_dev->features & NETIF_F_LRO; + /* If we're in loopback test, then pass the packet directly to the + * loopback layer, and free the rx_buf here + */ + if (unlikely(efx->loopback_selftest)) { + efx_loopback_rx_packet(efx, rx_buf->data, rx_buf->len); + efx_free_rx_buffer(efx, rx_buf); + goto done; + } + if (rx_buf->skb) { prefetch(skb_shinfo(rx_buf->skb)); diff --git a/drivers/net/sfc/selftest.c b/drivers/net/sfc/selftest.c new file mode 100644 index 0000000..cbda159 --- /dev/null +++ b/drivers/net/sfc/selftest.c @@ -0,0 +1,717 @@ +/**************************************************************************** + * Driver for Solarflare Solarstorm network controllers and boards + * Copyright 2005-2006 Fen Systems Ltd. + * Copyright 2006-2008 Solarflare Communications Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, incorporated herein by reference. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "net_driver.h" +#include "ethtool.h" +#include "efx.h" +#include "falcon.h" +#include "selftest.h" +#include "boards.h" +#include "workarounds.h" +#include "mac.h" + +/* + * Loopback test packet structure + * + * The self-test should stress every RSS vector, and unfortunately + * Falcon only performs RSS on TCP/UDP packets. + */ +struct efx_loopback_payload { + struct ethhdr header; + struct iphdr ip; + struct udphdr udp; + __be16 iteration; + const char msg[64]; +} __attribute__ ((packed)); + +/* Loopback test source MAC address */ +static const unsigned char payload_source[ETH_ALEN] = { + 0x00, 0x0f, 0x53, 0x1b, 0x1b, 0x1b, +}; + +static const char *payload_msg = + "Hello world! This is an Efx loopback test in progress!"; + +/** + * efx_selftest_state - persistent state during a selftest + * @flush: Drop all packets in efx_loopback_rx_packet + * @packet_count: Number of packets being used in this test + * @skbs: An array of skbs transmitted + * @rx_good: RX good packet count + * @rx_bad: RX bad packet count + * @payload: Payload used in tests + */ +struct efx_selftest_state { + int flush; + int packet_count; + struct sk_buff **skbs; + atomic_t rx_good; + atomic_t rx_bad; + struct efx_loopback_payload payload; +}; + +/************************************************************************** + * + * Configurable values + * + **************************************************************************/ + +/* Level of loopback testing + * + * The maximum packet burst length is 16**(n-1), i.e. + * + * - Level 0 : no packets + * - Level 1 : 1 packet + * - Level 2 : 17 packets (1 * 1 packet, 1 * 16 packets) + * - Level 3 : 273 packets (1 * 1 packet, 1 * 16 packet, 1 * 256 packets) + * + */ +static unsigned int loopback_test_level = 3; + +/************************************************************************** + * + * Interrupt and event queue testing + * + **************************************************************************/ + +/* Test generation and receipt of interrupts */ +static int efx_test_interrupts(struct efx_nic *efx, + struct efx_self_tests *tests) +{ + struct efx_channel *channel; + + EFX_LOG(efx, "testing interrupts\n"); + tests->interrupt = -1; + + /* Reset interrupt flag */ + efx->last_irq_cpu = -1; + smp_wmb(); + + /* ACK each interrupting event queue. Receiving an interrupt due to + * traffic before a test event is raised is considered a pass */ + efx_for_each_channel_with_interrupt(channel, efx) { + if (channel->work_pending) + efx_process_channel_now(channel); + if (efx->last_irq_cpu >= 0) + goto success; + } + + falcon_generate_interrupt(efx); + + /* Wait for arrival of test interrupt. */ + EFX_LOG(efx, "waiting for test interrupt\n"); + schedule_timeout_uninterruptible(HZ / 10); + if (efx->last_irq_cpu >= 0) + goto success; + + EFX_ERR(efx, "timed out waiting for interrupt\n"); + return -ETIMEDOUT; + + success: + EFX_LOG(efx, "test interrupt (mode %d) seen on CPU%d\n", + efx->interrupt_mode, efx->last_irq_cpu); + tests->interrupt = 1; + return 0; +} + +/* Test generation and receipt of non-interrupting events */ +static int efx_test_eventq(struct efx_channel *channel, + struct efx_self_tests *tests) +{ + unsigned int magic; + + /* Channel specific code, limited to 20 bits */ + magic = (0x00010150 + channel->channel); + EFX_LOG(channel->efx, "channel %d testing event queue with code %x\n", + channel->channel, magic); + + tests->eventq_dma[channel->channel] = -1; + tests->eventq_int[channel->channel] = 1; /* fake pass */ + tests->eventq_poll[channel->channel] = 1; /* fake pass */ + + /* Reset flag and zero magic word */ + channel->efx->last_irq_cpu = -1; + channel->eventq_magic = 0; + smp_wmb(); + + falcon_generate_test_event(channel, magic); + udelay(1); + + efx_process_channel_now(channel); + if (channel->eventq_magic != magic) { + EFX_ERR(channel->efx, "channel %d failed to see test event\n", + channel->channel); + return -ETIMEDOUT; + } else { + tests->eventq_dma[channel->channel] = 1; + } + + return 0; +} + +/* Test generation and receipt of interrupting events */ +static int efx_test_eventq_irq(struct efx_channel *channel, + struct efx_self_tests *tests) +{ + unsigned int magic, count; + + /* Channel specific code, limited to 20 bits */ + magic = (0x00010150 + channel->channel); + EFX_LOG(channel->efx, "channel %d testing event queue with code %x\n", + channel->channel, magic); + + tests->eventq_dma[channel->channel] = -1; + tests->eventq_int[channel->channel] = -1; + tests->eventq_poll[channel->channel] = -1; + + /* Reset flag and zero magic word */ + channel->efx->last_irq_cpu = -1; + channel->eventq_magic = 0; + smp_wmb(); + + falcon_generate_test_event(channel, magic); + + /* Wait for arrival of interrupt */ + count = 0; + do { + schedule_timeout_uninterruptible(HZ / 100); + + if (channel->work_pending) + efx_process_channel_now(channel); + + if (channel->eventq_magic == magic) + goto eventq_ok; + } while (++count < 2); + + EFX_ERR(channel->efx, "channel %d timed out waiting for event queue\n", + channel->channel); + + /* See if interrupt arrived */ + if (channel->efx->last_irq_cpu >= 0) { + EFX_ERR(channel->efx, "channel %d saw interrupt on CPU%d " + "during event queue test\n", channel->channel, + raw_smp_processor_id()); + tests->eventq_int[channel->channel] = 1; + } + + /* Check to see if event was received even if interrupt wasn't */ + efx_process_channel_now(channel); + if (channel->eventq_magic == magic) { + EFX_ERR(channel->efx, "channel %d event was generated, but " + "failed to trigger an interrupt\n", channel->channel); + tests->eventq_dma[channel->channel] = 1; + } + + return -ETIMEDOUT; + eventq_ok: + EFX_LOG(channel->efx, "channel %d event queue passed\n", + channel->channel); + tests->eventq_dma[channel->channel] = 1; + tests->eventq_int[channel->channel] = 1; + tests->eventq_poll[channel->channel] = 1; + return 0; +} + +/************************************************************************** + * + * PHY testing + * + **************************************************************************/ + +/* Check PHY presence by reading the PHY ID registers */ +static int efx_test_phy(struct efx_nic *efx, + struct efx_self_tests *tests) +{ + u16 physid1, physid2; + struct mii_if_info *mii = &efx->mii; + struct net_device *net_dev = efx->net_dev; + + if (efx->phy_type == PHY_TYPE_NONE) + return 0; + + EFX_LOG(efx, "testing PHY presence\n"); + tests->phy_ok = -1; + + physid1 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID1); + physid2 = mii->mdio_read(net_dev, mii->phy_id, MII_PHYSID2); + + if ((physid1 != 0x0000) && (physid1 != 0xffff) && + (physid2 != 0x0000) && (physid2 != 0xffff)) { + EFX_LOG(efx, "found MII PHY %d ID 0x%x:%x\n", + mii->phy_id, physid1, physid2); + tests->phy_ok = 1; + return 0; + } + + EFX_ERR(efx, "no MII PHY present with ID %d\n", mii->phy_id); + return -ENODEV; +} + +/************************************************************************** + * + * Loopback testing + * NB Only one loopback test can be executing concurrently. + * + **************************************************************************/ + +/* Loopback test RX callback + * This is called for each received packet during loopback testing. + */ +void efx_loopback_rx_packet(struct efx_nic *efx, + const char *buf_ptr, int pkt_len) +{ + struct efx_selftest_state *state = efx->loopback_selftest; + struct efx_loopback_payload *received; + struct efx_loopback_payload *payload; + + BUG_ON(!buf_ptr); + + /* If we are just flushing, then drop the packet */ + if ((state == NULL) || state->flush) + return; + + payload = &state->payload; + + received = (struct efx_loopback_payload *)(char *) buf_ptr; + received->ip.saddr = payload->ip.saddr; + received->ip.check = payload->ip.check; + + /* Check that header exists */ + if (pkt_len < sizeof(received->header)) { + EFX_ERR(efx, "saw runt RX packet (length %d) in %s loopback " + "test\n", pkt_len, LOOPBACK_MODE(efx)); + goto err; + } + + /* Check that the ethernet header exists */ + if (memcmp(&received->header, &payload->header, ETH_HLEN) != 0) { + EFX_ERR(efx, "saw non-loopback RX packet in %s loopback test\n", + LOOPBACK_MODE(efx)); + goto err; + } + + /* Check packet length */ + if (pkt_len != sizeof(*payload)) { + EFX_ERR(efx, "saw incorrect RX packet length %d (wanted %d) in " + "%s loopback test\n", pkt_len, (int)sizeof(*payload), + LOOPBACK_MODE(efx)); + goto err; + } + + /* Check that IP header matches */ + if (memcmp(&received->ip, &payload->ip, sizeof(payload->ip)) != 0) { + EFX_ERR(efx, "saw corrupted IP header in %s loopback test\n", + LOOPBACK_MODE(efx)); + goto err; + } + + /* Check that msg and padding matches */ + if (memcmp(&received->msg, &payload->msg, sizeof(received->msg)) != 0) { + EFX_ERR(efx, "saw corrupted RX packet in %s loopback test\n", + LOOPBACK_MODE(efx)); + goto err; + } + + /* Check that iteration matches */ + if (received->iteration != payload->iteration) { + EFX_ERR(efx, "saw RX packet from iteration %d (wanted %d) in " + "%s loopback test\n", ntohs(received->iteration), + ntohs(payload->iteration), LOOPBACK_MODE(efx)); + goto err; + } + + /* Increase correct RX count */ + EFX_TRACE(efx, "got loopback RX in %s loopback test\n", + LOOPBACK_MODE(efx)); + + atomic_inc(&state->rx_good); + return; + + err: +#ifdef EFX_ENABLE_DEBUG + if (atomic_read(&state->rx_bad) == 0) { + EFX_ERR(efx, "received packet:\n"); + print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, + buf_ptr, pkt_len, 0); + EFX_ERR(efx, "expected packet:\n"); + print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 0x10, 1, + &state->payload, sizeof(state->payload), 0); + } +#endif + atomic_inc(&state->rx_bad); +} + +/* Initialise an efx_selftest_state for a new iteration */ +static void efx_iterate_state(struct efx_nic *efx) +{ + struct efx_selftest_state *state = efx->loopback_selftest; + struct net_device *net_dev = efx->net_dev; + struct efx_loopback_payload *payload = &state->payload; + + /* Initialise the layerII header */ + memcpy(&payload->header.h_dest, net_dev->dev_addr, ETH_ALEN); + memcpy(&payload->header.h_source, &payload_source, ETH_ALEN); + payload->header.h_proto = htons(ETH_P_IP); + + /* saddr set later and used as incrementing count */ + payload->ip.daddr = htonl(INADDR_LOOPBACK); + payload->ip.ihl = 5; + payload->ip.check = htons(0xdead); + payload->ip.tot_len = htons(sizeof(*payload) - sizeof(struct ethhdr)); + payload->ip.version = IPVERSION; + payload->ip.protocol = IPPROTO_UDP; + + /* Initialise udp header */ + payload->udp.source = 0; + payload->udp.len = htons(sizeof(*payload) - sizeof(struct ethhdr) - + sizeof(struct iphdr)); + payload->udp.check = 0; /* checksum ignored */ + + /* Fill out payload */ + payload->iteration = htons(ntohs(payload->iteration) + 1); + memcpy(&payload->msg, payload_msg, sizeof(payload_msg)); + + /* Fill out remaining state members */ + atomic_set(&state->rx_good, 0); + atomic_set(&state->rx_bad, 0); + smp_wmb(); +} + +static int efx_tx_loopback(struct efx_tx_queue *tx_queue) +{ + struct efx_nic *efx = tx_queue->efx; + struct efx_selftest_state *state = efx->loopback_selftest; + struct efx_loopback_payload *payload; + struct sk_buff *skb; + int i, rc; + + /* Transmit N copies of buffer */ + for (i = 0; i < state->packet_count; i++) { + /* Allocate an skb, holding an extra reference for + * transmit completion counting */ + skb = alloc_skb(sizeof(state->payload), GFP_KERNEL); + if (!skb) + return -ENOMEM; + state->skbs[i] = skb; + skb_get(skb); + + /* Copy the payload in, incrementing the source address to + * exercise the rss vectors */ + payload = ((struct efx_loopback_payload *) + skb_put(skb, sizeof(state->payload))); + memcpy(payload, &state->payload, sizeof(state->payload)); + payload->ip.saddr = htonl(INADDR_LOOPBACK | (i << 2)); + + /* Ensure everything we've written is visible to the + * interrupt handler. */ + smp_wmb(); + + if (NET_DEV_REGISTERED(efx)) + netif_tx_lock_bh(efx->net_dev); + rc = efx_xmit(efx, tx_queue, skb); + if (NET_DEV_REGISTERED(efx)) + netif_tx_unlock_bh(efx->net_dev); + + if (rc != NETDEV_TX_OK) { + EFX_ERR(efx, "TX queue %d could not transmit packet %d " + "of %d in %s loopback test\n", tx_queue->queue, + i + 1, state->packet_count, LOOPBACK_MODE(efx)); + + /* Defer cleaning up the other skbs for the caller */ + kfree_skb(skb); + return -EPIPE; + } + } + + return 0; +} + +static int efx_rx_loopback(struct efx_tx_queue *tx_queue, + struct efx_loopback_self_tests *lb_tests) +{ + struct efx_nic *efx = tx_queue->efx; + struct efx_selftest_state *state = efx->loopback_selftest; + struct sk_buff *skb; + int tx_done = 0, rx_good, rx_bad; + int i, rc = 0; + + if (NET_DEV_REGISTERED(efx)) + netif_tx_lock_bh(efx->net_dev); + + /* Count the number of tx completions, and decrement the refcnt. Any + * skbs not already completed will be free'd when the queue is flushed */ + for (i=0; i < state->packet_count; i++) { + skb = state->skbs[i]; + if (skb && !skb_shared(skb)) + ++tx_done; + dev_kfree_skb_any(skb); + } + + if (NET_DEV_REGISTERED(efx)) + netif_tx_unlock_bh(efx->net_dev); + + /* Check TX completion and received packet counts */ + rx_good = atomic_read(&state->rx_good); + rx_bad = atomic_read(&state->rx_bad); + if (tx_done != state->packet_count) { + /* Don't free the skbs; they will be picked up on TX + * overflow or channel teardown. + */ + EFX_ERR(efx, "TX queue %d saw only %d out of an expected %d " + "TX completion events in %s loopback test\n", + tx_queue->queue, tx_done, state->packet_count, + LOOPBACK_MODE(efx)); + rc = -ETIMEDOUT; + /* Allow to fall through so we see the RX errors as well */ + } + + /* We may always be up to a flush away from our desired packet total */ + if (rx_good != state->packet_count) { + EFX_LOG(efx, "TX queue %d saw only %d out of an expected %d " + "received packets in %s loopback test\n", + tx_queue->queue, rx_good, state->packet_count, + LOOPBACK_MODE(efx)); + rc = -ETIMEDOUT; + /* Fall through */ + } + + /* Update loopback test structure */ + lb_tests->tx_sent[tx_queue->queue] += state->packet_count; + lb_tests->tx_done[tx_queue->queue] += tx_done; + lb_tests->rx_good += rx_good; + lb_tests->rx_bad += rx_bad; + + return rc; +} + +static int +efx_test_loopback(struct efx_tx_queue *tx_queue, + struct efx_loopback_self_tests *lb_tests) +{ + struct efx_nic *efx = tx_queue->efx; + struct efx_selftest_state *state = efx->loopback_selftest; + struct efx_channel *channel; + int i, rc = 0; + + for (i = 0; i < loopback_test_level; i++) { + /* Determine how many packets to send */ + state->packet_count = (efx->type->txd_ring_mask + 1) / 3; + state->packet_count = min(1 << (i << 2), state->packet_count); + state->skbs = kzalloc(sizeof(state->skbs[0]) * + state->packet_count, GFP_KERNEL); + state->flush = 0; + + EFX_LOG(efx, "TX queue %d testing %s loopback with %d " + "packets\n", tx_queue->queue, LOOPBACK_MODE(efx), + state->packet_count); + + efx_iterate_state(efx); + rc = efx_tx_loopback(tx_queue); + + /* NAPI polling is not enabled, so process channels synchronously */ + schedule_timeout_uninterruptible(HZ / 50); + efx_for_each_channel_with_interrupt(channel, efx) { + if (channel->work_pending) + efx_process_channel_now(channel); + } + + rc |= efx_rx_loopback(tx_queue, lb_tests); + kfree(state->skbs); + + if (rc) { + /* Wait a while to ensure there are no packets + * floating around after a failure. */ + schedule_timeout_uninterruptible(HZ / 10); + return rc; + } + } + + EFX_LOG(efx, "TX queue %d passed %s loopback test with a burst length " + "of %d packets\n", tx_queue->queue, LOOPBACK_MODE(efx), + state->packet_count); + + return rc; +} + +static int efx_test_loopbacks(struct efx_nic *efx, + struct efx_self_tests *tests, + unsigned int loopback_modes) +{ + struct efx_selftest_state *state = efx->loopback_selftest; + struct ethtool_cmd ecmd, ecmd_loopback; + struct efx_tx_queue *tx_queue; + enum efx_loopback_mode old_mode, mode; + int count, rc = 0, link_up; + + rc = efx_ethtool_get_settings(efx->net_dev, &ecmd); + if (rc) { + EFX_ERR(efx, "could not get GMII settings\n"); + return rc; + } + old_mode = efx->loopback_mode; + + /* Disable autonegotiation for the purposes of loopback */ + memcpy(&ecmd_loopback, &ecmd, sizeof(ecmd_loopback)); + if (ecmd_loopback.autoneg == AUTONEG_ENABLE) { + ecmd_loopback.autoneg = AUTONEG_DISABLE; + ecmd_loopback.duplex = DUPLEX_FULL; + ecmd_loopback.speed = SPEED_10000; + } + + rc = efx_ethtool_set_settings(efx->net_dev, &ecmd_loopback); + if (rc) { + EFX_ERR(efx, "could not disable autonegotiation\n"); + goto out; + } + tests->loopback_speed = ecmd_loopback.speed; + tests->loopback_full_duplex = ecmd_loopback.duplex; + + /* Test all supported loopback modes */ + for (mode = LOOPBACK_NONE; mode < LOOPBACK_TEST_MAX; mode++) { + if (!(loopback_modes & (1 << mode))) + continue; + + /* Move the port into the specified loopback mode. */ + state->flush = 1; + efx->loopback_mode = mode; + efx_reconfigure_port(efx); + + /* Wait for the PHY to signal the link is up */ + count = 0; + do { + struct efx_channel *channel = &efx->channel[0]; + + falcon_check_xmac(efx); + schedule_timeout_uninterruptible(HZ / 10); + if (channel->work_pending) + efx_process_channel_now(channel); + /* Wait for PHY events to be processed */ + flush_workqueue(efx->workqueue); + rmb(); + + /* efx->link_up can be 1 even if the XAUI link is down, + * (bug5762). Usually, it's not worth bothering with the + * difference, but for selftests, we need that extra + * guarantee that the link is really, really, up. + */ + link_up = efx->link_up; + if (!falcon_xaui_link_ok(efx)) + link_up = 0; + + } while ((++count < 20) && !link_up); + + /* The link should now be up. If it isn't, there is no point + * in attempting a loopback test */ + if (!link_up) { + EFX_ERR(efx, "loopback %s never came up\n", + LOOPBACK_MODE(efx)); + rc = -EIO; + goto out; + } + + EFX_LOG(efx, "link came up in %s loopback in %d iterations\n", + LOOPBACK_MODE(efx), count); + + /* Test every TX queue */ + efx_for_each_tx_queue(tx_queue, efx) { + rc |= efx_test_loopback(tx_queue, + &tests->loopback[mode]); + if (rc) + goto out; + } + } + + out: + /* Take out of loopback and restore PHY settings */ + state->flush = 1; + efx->loopback_mode = old_mode; + efx_ethtool_set_settings(efx->net_dev, &ecmd); + + return rc; +} + +/************************************************************************** + * + * Entry points + * + *************************************************************************/ + +/* Online (i.e. non-disruptive) testing + * This checks interrupt generation, event delivery and PHY presence. */ +int efx_online_test(struct efx_nic *efx, struct efx_self_tests *tests) +{ + struct efx_channel *channel; + int rc = 0; + + EFX_LOG(efx, "performing online self-tests\n"); + + rc |= efx_test_interrupts(efx, tests); + efx_for_each_channel(channel, efx) { + if (channel->has_interrupt) + rc |= efx_test_eventq_irq(channel, tests); + else + rc |= efx_test_eventq(channel, tests); + } + rc |= efx_test_phy(efx, tests); + + if (rc) + EFX_ERR(efx, "failed online self-tests\n"); + + return rc; +} + +/* Offline (i.e. disruptive) testing + * This checks MAC and PHY loopback on the specified port. */ +int efx_offline_test(struct efx_nic *efx, + struct efx_self_tests *tests, unsigned int loopback_modes) +{ + struct efx_selftest_state *state; + int rc = 0; + + EFX_LOG(efx, "performing offline self-tests\n"); + + /* Create a selftest_state structure to hold state for the test */ + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (state == NULL) { + rc = -ENOMEM; + goto out; + } + + /* Set the port loopback_selftest member. From this point on + * all received packets will be dropped. Mark the state as + * "flushing" so all inflight packets are dropped */ + BUG_ON(efx->loopback_selftest); + state->flush = 1; + efx->loopback_selftest = (void *)state; + + rc = efx_test_loopbacks(efx, tests, loopback_modes); + + efx->loopback_selftest = NULL; + wmb(); + kfree(state); + + out: + if (rc) + EFX_ERR(efx, "failed offline self-tests\n"); + + return rc; +} + diff --git a/drivers/net/sfc/selftest.h b/drivers/net/sfc/selftest.h new file mode 100644 index 0000000..f6999c2 --- /dev/null +++ b/drivers/net/sfc/selftest.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * Driver for Solarflare Solarstorm network controllers and boards + * Copyright 2005-2006 Fen Systems Ltd. + * Copyright 2006-2008 Solarflare Communications Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation, incorporated herein by reference. + */ + +#ifndef EFX_SELFTEST_H +#define EFX_SELFTEST_H + +#include "net_driver.h" + +/* + * Self tests + */ + +struct efx_loopback_self_tests { + int tx_sent[EFX_MAX_TX_QUEUES]; + int tx_done[EFX_MAX_TX_QUEUES]; + int rx_good; + int rx_bad; +}; + +/* Efx self test results + * For fields which are not counters, 1 indicates success and -1 + * indicates failure. + */ +struct efx_self_tests { + int interrupt; + int eventq_dma[EFX_MAX_CHANNELS]; + int eventq_int[EFX_MAX_CHANNELS]; + int eventq_poll[EFX_MAX_CHANNELS]; + int phy_ok; + int loopback_speed; + int loopback_full_duplex; + struct efx_loopback_self_tests loopback[LOOPBACK_TEST_MAX]; +}; + +extern void efx_loopback_rx_packet(struct efx_nic *efx, + const char *buf_ptr, int pkt_len); +extern int efx_online_test(struct efx_nic *efx, + struct efx_self_tests *tests); +extern int efx_offline_test(struct efx_nic *efx, + struct efx_self_tests *tests, + unsigned int loopback_modes); + +#endif /* EFX_SELFTEST_H */ diff --git a/drivers/net/sfc/tenxpress.c b/drivers/net/sfc/tenxpress.c index d8df031..b1cd6de 100644 --- a/drivers/net/sfc/tenxpress.c +++ b/drivers/net/sfc/tenxpress.c @@ -24,6 +24,11 @@ MDIO_MMDREG_DEVS0_PCS | \ MDIO_MMDREG_DEVS0_PHYXS) +#define TENXPRESS_LOOPBACKS ((1 << LOOPBACK_PHYXS) | \ + (1 << LOOPBACK_PCS) | \ + (1 << LOOPBACK_PMAPMD) | \ + (1 << LOOPBACK_NETWORK)) + /* We complain if we fail to see the link partner as 10G capable this many * times in a row (must be > 1 as sampling the autoneg. registers is racy) */ @@ -72,6 +77,10 @@ #define PMA_PMD_BIST_RXD_LBN (1) #define PMA_PMD_BIST_AFE_LBN (0) +/* Special Software reset register */ +#define PMA_PMD_EXT_CTRL_REG 49152 +#define PMA_PMD_EXT_SSR_LBN 15 + #define BIST_MAX_DELAY (1000) #define BIST_POLL_DELAY (10) @@ -86,6 +95,11 @@ #define PCS_TEST_SELECT_REG 0xd807 /* PRM 10.5.8 */ #define CLK312_EN_LBN 3 +/* PHYXS registers */ +#define PHYXS_TEST1 (49162) +#define LOOPBACK_NEAR_LBN (8) +#define LOOPBACK_NEAR_WIDTH (1) + /* Boot status register */ #define PCS_BOOT_STATUS_REG (0xd000) #define PCS_BOOT_FATAL_ERR_LBN (0) @@ -106,7 +120,9 @@ MODULE_PARM_DESC(crc_error_reset_threshold, struct tenxpress_phy_data { enum tenxpress_state state; + enum efx_loopback_mode loopback_mode; atomic_t bad_crc_count; + int tx_disabled; int bad_lp_tries; }; @@ -227,6 +243,35 @@ static int tenxpress_phy_init(struct efx_nic *efx) return rc; } +static int tenxpress_special_reset(struct efx_nic *efx) +{ + int rc, reg; + + EFX_TRACE(efx, "%s\n", __func__); + + /* Initiate reset */ + reg = mdio_clause45_read(efx, efx->mii.phy_id, + MDIO_MMD_PMAPMD, PMA_PMD_EXT_CTRL_REG); + reg |= (1 << PMA_PMD_EXT_SSR_LBN); + mdio_clause45_write(efx, efx->mii.phy_id, MDIO_MMD_PMAPMD, + PMA_PMD_EXT_CTRL_REG, reg); + + msleep(200); + + /* Wait for the blocks to come out of reset */ + rc = mdio_clause45_wait_reset_mmds(efx, + TENXPRESS_REQUIRED_DEVS); + if (rc < 0) + return rc; + + /* Try and reconfigure the device */ + rc = tenxpress_init(efx); + if (rc < 0) + return rc; + + return 0; +} + static void tenxpress_set_bad_lp(struct efx_nic *efx, int bad_lp) { struct tenxpress_phy_data *pd = efx->phy_data; @@ -301,11 +346,46 @@ static int tenxpress_link_ok(struct efx_nic *efx, int check_lp) return ok; } +static void tenxpress_phyxs_loopback(struct efx_nic *efx) +{ + int phy_id = efx->mii.phy_id; + int ctrl1, ctrl2; + + ctrl1 = ctrl2 = mdio_clause45_read(efx, phy_id, MDIO_MMD_PHYXS, + PHYXS_TEST1); + if (efx->loopback_mode == LOOPBACK_PHYXS) + ctrl2 |= (1 << LOOPBACK_NEAR_LBN); + else + ctrl2 &= ~(1 << LOOPBACK_NEAR_LBN); + if (ctrl1 != ctrl2) + mdio_clause45_write(efx, phy_id, MDIO_MMD_PHYXS, + PHYXS_TEST1, ctrl2); +} + static void tenxpress_phy_reconfigure(struct efx_nic *efx) { + struct tenxpress_phy_data *phy_data = efx->phy_data; + int loop_change = LOOPBACK_OUT_OF(phy_data, efx, + TENXPRESS_LOOPBACKS); + if (!tenxpress_state_is(efx, TENXPRESS_STATUS_NORMAL)) return; + /* When coming out of transmit disable, coming out of low power + * mode, or moving out of any PHY internal loopback mode, + * perform a special software reset */ + if ((phy_data->tx_disabled && !efx->tx_disabled) || + loop_change) { + (void) tenxpress_special_reset(efx); + falcon_reset_xaui(efx); + } + + mdio_clause45_transmit_disable(efx); + mdio_clause45_phy_reconfigure(efx); + tenxpress_phyxs_loopback(efx); + + phy_data->tx_disabled = efx->tx_disabled; + phy_data->loopback_mode = efx->loopback_mode; efx->link_up = tenxpress_link_ok(efx, 0); efx->link_options = GM_LPA_10000FULL; } @@ -433,4 +513,5 @@ struct efx_phy_operations falcon_tenxpress_phy_ops = { .clear_interrupt = tenxpress_phy_clear_interrupt, .reset_xaui = tenxpress_reset_xaui, .mmds = TENXPRESS_REQUIRED_DEVS, + .loopbacks = TENXPRESS_LOOPBACKS, }; diff --git a/drivers/net/sfc/xfp_phy.c b/drivers/net/sfc/xfp_phy.c index 66dd5bf..3b9f9dd 100644 --- a/drivers/net/sfc/xfp_phy.c +++ b/drivers/net/sfc/xfp_phy.c @@ -24,6 +24,10 @@ MDIO_MMDREG_DEVS0_PMAPMD | \ MDIO_MMDREG_DEVS0_PHYXS) +#define XFP_LOOPBACKS ((1 << LOOPBACK_PCS) | \ + (1 << LOOPBACK_PMAPMD) | \ + (1 << LOOPBACK_NETWORK)) + /****************************************************************************/ /* Quake-specific MDIO registers */ #define MDIO_QUAKE_LED0_REG (0xD006) @@ -35,6 +39,10 @@ void xfp_set_led(struct efx_nic *p, int led, int mode) mode); } +struct xfp_phy_data { + int tx_disabled; +}; + #define XFP_MAX_RESET_TIME 500 #define XFP_RESET_WAIT 10 @@ -72,18 +80,31 @@ static int xfp_reset_phy(struct efx_nic *efx) static int xfp_phy_init(struct efx_nic *efx) { + struct xfp_phy_data *phy_data; u32 devid = mdio_clause45_read_id(efx, MDIO_MMD_PHYXS); int rc; + phy_data = kzalloc(sizeof(struct xfp_phy_data), GFP_KERNEL); + efx->phy_data = (void *) phy_data; + EFX_INFO(efx, "XFP: PHY ID reg %x (OUI %x model %x revision" " %x)\n", devid, MDIO_ID_OUI(devid), MDIO_ID_MODEL(devid), MDIO_ID_REV(devid)); + phy_data->tx_disabled = efx->tx_disabled; + rc = xfp_reset_phy(efx); EFX_INFO(efx, "XFP: PHY init %s.\n", rc ? "failed" : "successful"); + if (rc < 0) + goto fail; + return 0; + + fail: + kfree(efx->phy_data); + efx->phy_data = NULL; return rc; } @@ -110,6 +131,16 @@ static int xfp_phy_check_hw(struct efx_nic *efx) static void xfp_phy_reconfigure(struct efx_nic *efx) { + struct xfp_phy_data *phy_data = efx->phy_data; + + /* Reset the PHY when moving from tx off to tx on */ + if (phy_data->tx_disabled && !efx->tx_disabled) + xfp_reset_phy(efx); + + mdio_clause45_transmit_disable(efx); + mdio_clause45_phy_reconfigure(efx); + + phy_data->tx_disabled = efx->tx_disabled; efx->link_up = xfp_link_ok(efx); efx->link_options = GM_LPA_10000FULL; } @@ -119,6 +150,10 @@ static void xfp_phy_fini(struct efx_nic *efx) { /* Clobber the LED if it was blinking */ efx->board_info.blink(efx, 0); + + /* Free the context block */ + kfree(efx->phy_data); + efx->phy_data = NULL; } struct efx_phy_operations falcon_xfp_phy_ops = { @@ -129,4 +164,5 @@ struct efx_phy_operations falcon_xfp_phy_ops = { .clear_interrupt = xfp_phy_clear_interrupt, .reset_xaui = efx_port_dummy_op_void, .mmds = XFP_REQUIRED_DEVS, + .loopbacks = XFP_LOOPBACKS, }; -- cgit v1.1 From a300344ab9b77130310fc225fdc7677e129b1163 Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Tue, 6 May 2008 14:34:35 -0700 Subject: sky2: fix simple define thinko noticed while browsing code, apparent thinko. compile tested only. Signed-off-by: Jesse Brandeburg CC: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 7bb3ba9..c0a5eea 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -1966,13 +1966,13 @@ struct sky2_status_le { struct tx_ring_info { struct sk_buff *skb; DECLARE_PCI_UNMAP_ADDR(mapaddr); - DECLARE_PCI_UNMAP_ADDR(maplen); + DECLARE_PCI_UNMAP_LEN(maplen); }; struct rx_ring_info { struct sk_buff *skb; dma_addr_t data_addr; - DECLARE_PCI_UNMAP_ADDR(data_size); + DECLARE_PCI_UNMAP_LEN(data_size); dma_addr_t frag_addr[ETH_JUMBO_MTU >> PAGE_SHIFT]; }; -- cgit v1.1 From e21fd4f07dd0c2630c3db41f419e4c658d0dee2c Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Thu, 8 May 2008 11:33:03 +0100 Subject: DM9000: Add __devinit and __devexit attributes to probe and remove There were missing __dev* annotations for the dm9000_probe() and dm9000_drv_remove() functions. Signed-off-by: Enrico Scholz Signed-off-by: Ben Dooks Signed-off-by: Jeff Garzik --- drivers/net/dm9000.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index e6fe261..273e654a 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -503,7 +503,7 @@ dm9000_release_board(struct platform_device *pdev, struct board_info *db) /* * Search DM9000 board, allocate space and register it */ -static int +static int __devinit dm9000_probe(struct platform_device *pdev) { struct dm9000_plat_data *pdata = pdev->dev.platform_data; @@ -1372,7 +1372,7 @@ dm9000_drv_resume(struct platform_device *dev) return 0; } -static int +static int __devexit dm9000_drv_remove(struct platform_device *pdev) { struct net_device *ndev = platform_get_drvdata(pdev); @@ -1393,7 +1393,7 @@ static struct platform_driver dm9000_driver = { .owner = THIS_MODULE, }, .probe = dm9000_probe, - .remove = dm9000_drv_remove, + .remove = __devexit_p(dm9000_drv_remove), .suspend = dm9000_drv_suspend, .resume = dm9000_drv_resume, }; -- cgit v1.1 From 37d5dca6af6b62bbb2c63f46a06cb07d0cf4522b Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Thu, 8 May 2008 11:35:13 +0100 Subject: DM9000: Update and fix driver debugging messages There was a missing newline in a dev_dbg() message. Values read from/written into PHY registers might be for interest too, so I added new dbg messages there. Signed-off-by: Enrico Scholz Signed-off-by: Ben Dooks Signed-off-by: Jeff Garzik --- drivers/net/dm9000.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index 273e654a..7c49f33 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -525,7 +525,7 @@ dm9000_probe(struct platform_device *pdev) SET_NETDEV_DEV(ndev, &pdev->dev); - dev_dbg(&pdev->dev, "dm9000_probe()"); + dev_dbg(&pdev->dev, "dm9000_probe()\n"); /* setup board info structure */ db = (struct board_info *) ndev->priv; @@ -1288,6 +1288,8 @@ dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) spin_unlock_irqrestore(&db->lock,flags); mutex_unlock(&db->addr_lock); + + dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret); return ret; } @@ -1301,6 +1303,7 @@ dm9000_phy_write(struct net_device *dev, int phyaddr_unused, int reg, int value) unsigned long flags; unsigned long reg_save; + dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); mutex_lock(&db->addr_lock); spin_lock_irqsave(&db->lock,flags); -- cgit v1.1 From 8f5bf5f25cdf9270f33ed347c582a3a451d3c38a Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 8 May 2008 11:36:42 +0100 Subject: DM9000: Use delayed work to update MII PHY state Periodically check the MII PHY status to ensure that the network layer's link status is updated and the user informed of any changes. Signed-off-by: Ben Dooks Signed-off-by: Jeff Garzik --- drivers/net/dm9000.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index 7c49f33..d45bcd2 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -117,6 +117,9 @@ typedef struct board_info { struct mutex addr_lock; /* phy and eeprom access lock */ + struct delayed_work phy_poll; + struct net_device *ndev; + spinlock_t lock; struct mii_if_info mii; @@ -297,6 +300,10 @@ static void dm9000_set_io(struct board_info *db, int byte_width) } } +static void dm9000_schedule_poll(board_info_t *db) +{ + schedule_delayed_work(&db->phy_poll, HZ * 2); +} /* Our watchdog timed out. Called by the networking layer */ static void dm9000_timeout(struct net_device *dev) @@ -465,6 +472,17 @@ static const struct ethtool_ops dm9000_ethtool_ops = { .set_eeprom = dm9000_set_eeprom, }; +static void +dm9000_poll_work(struct work_struct *w) +{ + struct delayed_work *dw = container_of(w, struct delayed_work, work); + board_info_t *db = container_of(dw, board_info_t, phy_poll); + + mii_check_media(&db->mii, netif_msg_link(db), 0); + + if (netif_running(db->ndev)) + dm9000_schedule_poll(db); +} /* dm9000_release_board * @@ -532,10 +550,14 @@ dm9000_probe(struct platform_device *pdev) memset(db, 0, sizeof (*db)); db->dev = &pdev->dev; + db->ndev = ndev; spin_lock_init(&db->lock); mutex_init(&db->addr_lock); + INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work); + + if (pdev->num_resources < 2) { ret = -ENODEV; goto out; @@ -761,6 +783,8 @@ dm9000_open(struct net_device *dev) mii_check_media(&db->mii, netif_msg_link(db), 1); netif_start_queue(dev); + + dm9000_schedule_poll(db); return 0; } @@ -879,6 +903,8 @@ dm9000_stop(struct net_device *ndev) if (netif_msg_ifdown(db)) dev_dbg(db->dev, "shutting down %s\n", ndev->name); + cancel_delayed_work(&db->phy_poll); + netif_stop_queue(ndev); netif_carrier_off(ndev); -- cgit v1.1 From 993245908ec35c071315479e20602577b7b5dde6 Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Wed, 7 May 2008 13:42:33 -0700 Subject: New maintainer for Intel ethernet adapters I'm handing over maintainership to Jeff Kirsher and moving on to other Linux/Open Source work within Intel. Good luck to Jeff ;) Signed-off-by: Auke Kok Signed-off-by: Jeff Garzik --- MAINTAINERS | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index c3a533d..0cc47b9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2104,12 +2104,10 @@ L: netdev@vger.kernel.org S: Maintained INTEL ETHERNET DRIVERS (e100/e1000/e1000e/igb/ixgb/ixgbe) -P: Auke Kok -M: auke-jan.h.kok@intel.com -P: Jesse Brandeburg -M: jesse.brandeburg@intel.com P: Jeff Kirsher M: jeffrey.t.kirsher@intel.com +P: Jesse Brandeburg +M: jesse.brandeburg@intel.com P: Bruce Allan M: bruce.w.allan@intel.com P: John Ronciak -- cgit v1.1 From 9a28dbf8af11d127bf1c644143e7882cb91515dd Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Mon, 12 May 2008 22:45:15 -0700 Subject: sparc64: Use a TS_RESTORE_SIGMASK This mirrors x86 changeset 5a8da0ea82db6fa9737041381079fd16f25dcce2 ("signals: x86 TS_RESTORE_SIGMASK") on sparc64. Signed-off-by: David S. Miller --- arch/sparc64/kernel/rtrap.S | 6 +++--- arch/sparc64/kernel/signal.c | 21 +++++++++++---------- arch/sparc64/kernel/signal32.c | 13 ++++++------- include/asm-sparc64/thread_info.h | 28 ++++++++++++++++++++++++---- 4 files changed, 44 insertions(+), 24 deletions(-) diff --git a/arch/sparc64/kernel/rtrap.S b/arch/sparc64/kernel/rtrap.S index b9b785f..16689b2 100644 --- a/arch/sparc64/kernel/rtrap.S +++ b/arch/sparc64/kernel/rtrap.S @@ -46,7 +46,7 @@ __handle_user_windows: wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate ldx [%g6 + TI_FLAGS], %l0 -1: andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 +1: andcc %l0, _TIF_SIGPENDING, %g0 be,pt %xcc, __handle_user_windows_continue nop mov %l5, %o1 @@ -86,7 +86,7 @@ __handle_perfctrs: wrpr %g0, RTRAP_PSTATE, %pstate wrpr %g0, RTRAP_PSTATE_IRQOFF, %pstate ldx [%g6 + TI_FLAGS], %l0 -1: andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 +1: andcc %l0, _TIF_SIGPENDING, %g0 be,pt %xcc, __handle_perfctrs_continue sethi %hi(TSTATE_PEF), %o0 @@ -195,7 +195,7 @@ __handle_preemption_continue: andcc %l1, %o0, %g0 andcc %l0, _TIF_NEED_RESCHED, %g0 bne,pn %xcc, __handle_preemption - andcc %l0, (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), %g0 + andcc %l0, _TIF_SIGPENDING, %g0 bne,pn %xcc, __handle_signal __handle_signal_continue: ldub [%g6 + TI_WSAVED], %o2 diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 2378482..6e4dc67 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -247,7 +247,9 @@ static long _sigpause_common(old_sigset_t set) current->state = TASK_INTERRUPTIBLE; schedule(); - set_thread_flag(TIF_RESTORE_SIGMASK); + + set_restore_sigmask(); + return -ERESTARTNOHAND; } @@ -537,7 +539,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) } else restart_syscall = 0; - if (test_thread_flag(TIF_RESTORE_SIGMASK)) + if (current_thread_info()->status & TS_RESTORE_SIGMASK) oldset = ¤t->saved_sigmask; else oldset = ¤t->blocked; @@ -566,13 +568,12 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) syscall_restart(orig_i0, regs, &ka.sa); handle_signal(signr, &ka, &info, oldset, regs); - /* a signal was successfully delivered; the saved + /* A signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag. + * clear the TS_RESTORE_SIGMASK flag. */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; return; } if (restart_syscall && @@ -591,17 +592,17 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) regs->tnpc -= 4; } - /* if there's no signal to deliver, we just put the saved sigmask + /* If there's no signal to deliver, we just put the saved sigmask * back */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } } void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags) { - if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + if (thread_info_flags & _TIF_SIGPENDING) do_signal(regs, orig_i0); } diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 3f19e9a..97cdd1b 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -788,13 +788,12 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, syscall_restart32(orig_i0, regs, &ka.sa); handle_signal32(signr, &ka, &info, oldset, regs); - /* a signal was successfully delivered; the saved + /* A signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag. + * clear the TS_RESTORE_SIGMASK flag. */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; return; } if (restart_syscall && @@ -813,11 +812,11 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, regs->tnpc -= 4; } - /* if there's no signal to deliver, we just put the saved sigmask + /* If there's no signal to deliver, we just put the saved sigmask * back */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); + if (current_thread_info()->status & TS_RESTORE_SIGMASK) { + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); } } diff --git a/include/asm-sparc64/thread_info.h b/include/asm-sparc64/thread_info.h index 71e42d1..e5873e3 100644 --- a/include/asm-sparc64/thread_info.h +++ b/include/asm-sparc64/thread_info.h @@ -38,7 +38,7 @@ struct thread_info { struct task_struct *task; unsigned long flags; __u8 fpsaved[7]; - __u8 pad; + __u8 status; unsigned long ksp; /* D$ line 2 */ @@ -217,7 +217,7 @@ register struct thread_info *current_thread_info_reg asm("g6"); * nop */ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */ -#define TIF_RESTORE_SIGMASK 1 /* restore signal mask in do_signal() */ +/* flags bit 1 is available */ #define TIF_SIGPENDING 2 /* signal pending */ #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ #define TIF_PERFCTR 4 /* performance counters active */ @@ -244,14 +244,34 @@ register struct thread_info *current_thread_info_reg asm("g6"); #define _TIF_32BIT (1<status |= TS_RESTORE_SIGMASK; + set_bit(TIF_SIGPENDING, &ti->flags); +} +#endif /* !__ASSEMBLY__ */ + #endif /* __KERNEL__ */ #endif /* _ASM_THREAD_INFO_H */ -- cgit v1.1 From a1c1f281b84a751fdb5ff919da3b09df7297619f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Tue, 13 May 2008 02:53:26 -0700 Subject: tcp FRTO: Fix fallback to conventional recovery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It seems that commit 009a2e3e4ec ("[TCP] FRTO: Improve interoperability with other undo_marker users") run into another land-mine which caused fallback to conventional recovery to break: 1. Cumulative ACK arrives after FRTO retransmission 2. tcp_try_to_open sees zero retrans_out, clears retrans_stamp which should be kept like in CA_Loss state it would be 3. undo_marker change allowed tcp_packet_delayed to return true because of the cleared retrans_stamp once FRTO is terminated causing LossUndo to occur, which means all loss markings FRTO made are reverted. This means that the conventional recovery basically recovered one loss per RTT, which is not that efficient. It was quite unobvious that the undo_marker change broken something like this, I had a quite long session to track it down because of the non-intuitiviness of the bug (luckily I had a trivial reproducer at hand and I was also able to learn to use kprobes in the process as well :-)). This together with the NewReno+FRTO fix and FRTO in-order workaround this fixes Damon's problems, this and the first mentioned are enough to fix Bugzilla #10063. Signed-off-by: Ilpo Järvinen Reported-by: Damon L. Chesser Tested-by: Damon L. Chesser Tested-by: Sebastian Hyrwall Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 26c9369..d6edb98 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -2482,7 +2482,7 @@ static void tcp_try_to_open(struct sock *sk, int flag) tcp_verify_left_out(tp); - if (tp->retrans_out == 0) + if (!tp->frto_counter && tp->retrans_out == 0) tp->retrans_stamp = 0; if (flag & FLAG_ECE) -- cgit v1.1 From 79d44516b4b178ffb6e2159c75584cfcfc097914 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Tue, 13 May 2008 02:54:19 -0700 Subject: tcp FRTO: work-around inorder receivers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If receiver consumes segments successfully only in-order, FRTO fallback to conventional recovery produces RTO loop because FRTO's forward transmissions will always get dropped and need to be resent, yet by default they're not marked as lost (which are the only segments we will retransmit in CA_Loss). Price to pay about this is occassionally unnecessarily retransmitting the forward transmission(s). SACK blocks help a bit to avoid this, so it's mainly a concern for NewReno case though SACK is not fully immune either. This change has a side-effect of fixing SACKFRTO problem where it didn't have snd_nxt of the RTO time available anymore when fallback become necessary (this problem would have only occured when RTO would occur for two or more segments and ECE arrives in step 3; no need to figure out how to fix that unless the TODO item of selective behavior is considered in future). Signed-off-by: Ilpo Järvinen Reported-by: Damon L. Chesser Tested-by: Damon L. Chesser Signed-off-by: David S. Miller --- net/ipv4/tcp_input.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index d6edb98..b54d9d3 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -1842,9 +1842,16 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag) TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_RETRANS; } - /* Don't lost mark skbs that were fwd transmitted after RTO */ - if (!(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED) && - !after(TCP_SKB_CB(skb)->end_seq, tp->frto_highmark)) { + /* Marking forward transmissions that were made after RTO lost + * can cause unnecessary retransmissions in some scenarios, + * SACK blocks will mitigate that in some but not in all cases. + * We used to not mark them but it was causing break-ups with + * receivers that do only in-order receival. + * + * TODO: we could detect presence of such receiver and select + * different behavior per flow. + */ + if (!(TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) { TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; tp->lost_out += tcp_skb_pcount(skb); } @@ -1860,7 +1867,7 @@ static void tcp_enter_frto_loss(struct sock *sk, int allowed_segments, int flag) tp->reordering = min_t(unsigned int, tp->reordering, sysctl_tcp_reordering); tcp_set_ca_state(sk, TCP_CA_Loss); - tp->high_seq = tp->frto_highmark; + tp->high_seq = tp->snd_nxt; TCP_ECN_queue_cwr(tp); tcp_clear_retrans_hints_partial(tp); -- cgit v1.1 From bf91141d3565b35fb2a44364bfb874a3be3c12b6 Mon Sep 17 00:00:00 2001 From: maximilian attems Date: Fri, 9 May 2008 13:43:09 +0200 Subject: [ALSA] emux midi synthesizer doesn't honor SOFT_PEDAL-release event When the hardware wavetable synthesizer of an Creative SB Audigy or SB Live! card (with emu10k chip) receives the MIDI SOFT_PEADAL-press event (?? 67 127) the appropriate voice is attenuted. Unfortunately when the pedal is released (event ?? 67 0) the voice does not get it's original volume again. Boolean MIDI controls should interpret 0..63 as false and 64..127 as true. Thanks to Clemens Ladisch for review and correction. Original patch from "Uwe Kraeger" Submitted to http://bugs.debian.org/474312 Signed-off-by: maximilian attems Cc: uwe_debbug@arcor.de Cc: Clemens Ladisch Signed-off-by: Takashi Iwai --- sound/synth/emux/emux_synth.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c index 478369b..b343818 100644 --- a/sound/synth/emux/emux_synth.c +++ b/sound/synth/emux/emux_synth.c @@ -341,8 +341,12 @@ snd_emux_control(void *p, int type, struct snd_midi_channel *chan) case MIDI_CTL_SOFT_PEDAL: #ifdef SNDRV_EMUX_USE_RAW_EFFECT /* FIXME: this is an emulation */ - snd_emux_send_effect(port, chan, EMUX_FX_CUTOFF, -160, + if (chan->control[type] >= 64) + snd_emux_send_effect(port, chan, EMUX_FX_CUTOFF, -160, EMUX_FX_FLAG_ADD); + else + snd_emux_send_effect(port, chan, EMUX_FX_CUTOFF, 0, + EMUX_FX_FLAG_OFF); #endif break; -- cgit v1.1 From 3a3bd960a0b7bb26604b1270a8b4cafdc5883040 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Fri, 9 May 2008 13:43:55 +0200 Subject: [ALSA] soc - fsl_ssi.c fix "BUG: scheduling while atomic" This patch fixes following bug caught with PREEMPT enabled: root@b1:~# cat /dev/dsp > /dev/null BUG: scheduling while atomic: cat/965/0x00000003 Call Trace: [df165ce0] [c0008e84] show_stack+0x4c/0x1ac (unreliable) [df165d20] [c001c18c] __schedule_bug+0x64/0x78 [df165d30] [c02b3344] schedule+0x2d8/0x334 [df165d70] [c02b3674] schedule_timeout+0x64/0xe4 [df165db0] [c002c05c] msleep+0x1c/0x34 [df165dc0] [c01f2fe0] fsl_ssi_trigger+0x130/0x144 [df165dd0] [c01ece54] soc_pcm_trigger+0x94/0xb8 [df165df0] [c01da764] snd_pcm_do_start+0x48/0x60 [df165e00] [c01da630] snd_pcm_action_single+0x4c/0xb4 [df165e20] [c01e0f50] snd_pcm_lib_read1+0x2a0/0x2d4 [df165e70] [c01ec274] snd_pcm_oss_read3+0xf0/0x13c [df165eb0] [c01ec2e4] snd_pcm_oss_read2+0x24/0x4c [df165ec0] [c01ec4ac] snd_pcm_oss_read+0x1a0/0x1f0 [df165ef0] [c0076478] vfs_read+0xb4/0x108 [df165f10] [c00768cc] sys_read+0x4c/0x90 [df165f40] [c00117a4] ret_from_syscall+0x0/0x38 Acked-by: Timur Tabi Signed-off-by: Mark Brown Signed-off-by: Takashi Iwai --- sound/soc/fsl/fsl_ssi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index b2a11b0..f588545 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -416,7 +416,7 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd) * to put data into its FIFO. Without it, ALSA starts * to complain about overruns. */ - msleep(1); + mdelay(1); } break; -- cgit v1.1 From 5b006137f47622dbd4a5aa2ba4010202cbc31667 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Fri, 9 May 2008 15:05:41 +0200 Subject: [ALSA] ASoC: Fix TLV320AIC3X mono line output interconnect There is no endpoint called MONOLOUT but MONO_LOUT. Signed-off-by: Jarkko Nikula Signed-off-by: Takashi Iwai --- sound/soc/codecs/tlv320aic3x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 630684f..09b1661 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -539,8 +539,8 @@ static const char *intercon[][3] = { {"HPRCOM", NULL, "Right HP Com"}, /* Mono Output */ - {"MONOLOUT", NULL, "Mono Out"}, - {"MONOLOUT", NULL, "Mono Out"}, + {"MONO_LOUT", NULL, "Mono Out"}, + {"MONO_LOUT", NULL, "Mono Out"}, /* Left Input */ {"Left Line1L Mux", "single-ended", "LINE1L"}, -- cgit v1.1 From 392abe9cb36f04ccdda9c96938077b0d43f2b50b Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Tue, 13 May 2008 14:03:40 +0200 Subject: [ALSA] ASoC: build fix for snd_soc_info_bool_ext I suspect that snd_ctl_boolean_mono should have been snd_ctl_boolean_mono_info instead. This fixes the build for magician. Signed-off-by: Philipp Zabel Acked-by: Mark Brown Signed-off-by: Takashi Iwai --- include/sound/soc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index e6ea6f7..d3c8c03 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -238,7 +238,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo); -#define snd_soc_info_bool_ext snd_ctl_boolean_mono +#define snd_soc_info_bool_ext snd_ctl_boolean_mono_info int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol); int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, -- cgit v1.1 From 3c17279137bf8318438510b48229d4236f773da4 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Tue, 13 May 2008 16:02:04 +0200 Subject: [ALSA] ASoC: Fix wrong enum count for jack_function in N810 machine driver Fix this typo and avoid similar errors by using ARRAY_SIZE macro. Signed-off-by: Jarkko Nikula Signed-off-by: Takashi Iwai --- sound/soc/omap/n810.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c index 83b1eb4..6533563 100644 --- a/sound/soc/omap/n810.c +++ b/sound/soc/omap/n810.c @@ -188,8 +188,8 @@ static const char *audio_map[][3] = { static const char *spk_function[] = {"Off", "On"}; static const char *jack_function[] = {"Off", "Headphone"}; static const struct soc_enum n810_enum[] = { - SOC_ENUM_SINGLE_EXT(2, spk_function), - SOC_ENUM_SINGLE_EXT(3, jack_function), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), + SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(jack_function), jack_function), }; static const struct snd_kcontrol_new aic33_n810_controls[] = { -- cgit v1.1 From 53c258787427ea43ebfa76fefa6534cae507e521 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:47 -0700 Subject: uml: redo host capability detection and disabling Redo how host capabilities are recorded at startup and disabled on the command line. There are now explicit variables saying what's been disabled by the command line rather than the implicitness of the have_* variable being zero. The capability variables now start at zero and are set to one as their capabilities are found to be present on the host. Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/os-Linux/start_up.c | 81 +++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 997d019..b4b36e0 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -23,6 +23,7 @@ #include "mem_user.h" #include "ptrace_user.h" #include "registers.h" +#include "skas.h" #include "skas_ptrace.h" static void ptrace_child(void) @@ -140,14 +141,27 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit) } /* Changed only during early boot */ -int ptrace_faultinfo = 1; -int ptrace_ldt = 1; -int proc_mm = 1; -int skas_needs_stub = 0; +int ptrace_faultinfo; +static int disable_ptrace_faultinfo; + +int ptrace_ldt; +static int disable_ptrace_ldt; + +int proc_mm; +static int disable_proc_mm; + +int have_switch_mm; +static int disable_switch_mm; + +int skas_needs_stub; static int __init skas0_cmd_param(char *str, int* add) { - ptrace_faultinfo = proc_mm = 0; + disable_ptrace_faultinfo = 1; + disable_ptrace_ldt = 1; + disable_proc_mm = 1; + disable_switch_mm = 1; + return 0; } @@ -157,15 +171,12 @@ static int __init mode_skas0_cmd_param(char *str, int* add) __attribute__((alias("skas0_cmd_param"))); __uml_setup("skas0", skas0_cmd_param, - "skas0\n" - " Disables SKAS3 usage, so that SKAS0 is used, unless \n" - " you specify mode=tt.\n\n"); +"skas0\n" +" Disables SKAS3 and SKAS4 usage, so that SKAS0 is used\n\n"); __uml_setup("mode=skas0", mode_skas0_cmd_param, - "mode=skas0\n" - " Disables SKAS3 usage, so that SKAS0 is used, unless you \n" - " specify mode=tt. Note that this was recently added - on \n" - " older kernels you must use simply \"skas0\".\n\n"); +"mode=skas0\n" +" Disables SKAS3 and SKAS4 usage, so that SKAS0 is used.\n\n"); /* Changed only during early boot */ static int force_sysemu_disabled = 0; @@ -360,7 +371,7 @@ void __init os_early_checks(void) static int __init noprocmm_cmd_param(char *str, int* add) { - proc_mm = 0; + disable_proc_mm = 1; return 0; } @@ -372,7 +383,7 @@ __uml_setup("noprocmm", noprocmm_cmd_param, static int __init noptracefaultinfo_cmd_param(char *str, int* add) { - ptrace_faultinfo = 0; + disable_ptrace_faultinfo = 1; return 0; } @@ -384,7 +395,7 @@ __uml_setup("noptracefaultinfo", noptracefaultinfo_cmd_param, static int __init noptraceldt_cmd_param(char *str, int* add) { - ptrace_ldt = 0; + disable_ptrace_ldt = 1; return 0; } @@ -404,17 +415,15 @@ static inline void check_skas3_ptrace_faultinfo(void) n = ptrace(PTRACE_FAULTINFO, pid, 0, &fi); if (n < 0) { - ptrace_faultinfo = 0; if (errno == EIO) non_fatal("not found\n"); else perror("not found"); - } + } else if (disable_ptrace_faultinfo) + non_fatal("found but disabled on command line\n"); else { - if (!ptrace_faultinfo) - non_fatal("found but disabled on command line\n"); - else - non_fatal("found\n"); + ptrace_faultinfo = 1; + non_fatal("found\n"); } stop_ptraced_child(pid, 1, 1); @@ -437,38 +446,30 @@ static inline void check_skas3_ptrace_ldt(void) if (n < 0) { if (errno == EIO) non_fatal("not found\n"); - else { + else perror("not found"); - } - ptrace_ldt = 0; - } + } else if (disable_ptrace_ldt) + non_fatal("found, but use is disabled\n"); else { - if (ptrace_ldt) - non_fatal("found\n"); - else - non_fatal("found, but use is disabled\n"); + ptrace_ldt = 1; + non_fatal("found\n"); } stop_ptraced_child(pid, 1, 1); -#else - /* PTRACE_LDT might be disabled via cmdline option. - * We want to override this, else we might use the stub - * without real need - */ - ptrace_ldt = 1; #endif } static inline void check_skas3_proc_mm(void) { non_fatal(" - /proc/mm..."); - if (access("/proc/mm", W_OK) < 0) { - proc_mm = 0; + if (access("/proc/mm", W_OK) < 0) perror("not found"); - } - else if (!proc_mm) + else if (disable_proc_mm) non_fatal("found but disabled on command line\n"); - else non_fatal("found\n"); + else { + proc_mm = 1; + non_fatal("found\n"); + } } void can_do_skas(void) -- cgit v1.1 From 96cee3044dca2e6510ca7cc276d1eac34a1cfd51 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:48 -0700 Subject: uml: style fixes A few random style fixes. Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/skas_ptrace.h | 13 +------------ arch/um/include/sysdep-i386/sigcontext.h | 2 +- arch/um/kernel/um_arch.c | 2 +- arch/um/os-Linux/skas/process.c | 2 +- 4 files changed, 4 insertions(+), 15 deletions(-) diff --git a/arch/um/include/skas_ptrace.h b/arch/um/include/skas_ptrace.h index cd2327d..3d31bba 100644 --- a/arch/um/include/skas_ptrace.h +++ b/arch/um/include/skas_ptrace.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -12,14 +12,3 @@ #include "sysdep/skas_ptrace.h" #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/include/sysdep-i386/sigcontext.h b/arch/um/include/sysdep-i386/sigcontext.h index 67e7712..f583c87 100644 --- a/arch/um/include/sysdep-i386/sigcontext.h +++ b/arch/um/include/sysdep-i386/sigcontext.h @@ -10,7 +10,7 @@ #define IP_RESTART_SYSCALL(ip) ((ip) -= 2) -#define GET_FAULTINFO_FROM_SC(fi,sc) \ +#define GET_FAULTINFO_FROM_SC(fi, sc) \ { \ (fi).cr2 = SC_CR2(sc); \ (fi).error_code = SC_ERR(sc); \ diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 56deed6..82058ac 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -150,7 +150,7 @@ __uml_setup("root=", uml_root_setup, static int __init no_skas_debug_setup(char *line, int *add) { printf("'debug' is not necessary to gdb UML in skas mode - run \n"); - printf("'gdb linux'"); + printf("'gdb linux'\n"); return 0; } diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 1e8cba6..6be028c 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -442,7 +442,7 @@ void userspace(struct uml_pt_regs *regs) unblock_signals(); break; default: - printk(UM_KERN_ERR "userspace - child stopped " + printk(UM_KERN_ERR "userspace - child stopped " "with signal %d\n", sig); fatal_sigsegv(); } -- cgit v1.1 From a0612b1f0b3d851458dafe5886e33d58c1967440 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:49 -0700 Subject: uml: hppfs fixes hppfs tidying and fixes noticed during hch's get_inode work - style fixes a copy_to_user got its return value checked hppfs_write no longer fiddles file->f_pos because it gets and returns pos in its arguments hppfs_delete_inode dputs the underlyng procfs dentry stored in its private data and mntputs the vfsmnt stashed in s_fs_info hppfs_put_super no longer needs to mntput the s_fs_info, so it no longer needs to exist hppfs_readlink and hppfs_follow_link were doing a bunch of stuff with a struct file which they didn't use there is now a ->permission which calls generic_permission get_inode was always returning 0 for some reason - it now returns an inode if nothing bad happened Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hppfs/hppfs_kern.c | 82 +++++++++++++++++++-------------------------------- 1 file changed, 30 insertions(+), 52 deletions(-) diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index 8601d8e..65077aa 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c @@ -33,7 +33,7 @@ struct hppfs_private { }; struct hppfs_inode_info { - struct dentry *proc_dentry; + struct dentry *proc_dentry; struct inode vfs_inode; }; @@ -52,7 +52,7 @@ static int is_pid(struct dentry *dentry) int i; sb = dentry->d_sb; - if ((sb->s_op != &hppfs_sbops) || (dentry->d_parent != sb->s_root)) + if (dentry->d_parent != sb->s_root) return 0; for (i = 0; i < dentry->d_name.len; i++) { @@ -136,7 +136,7 @@ static int file_removed(struct dentry *dentry, const char *file) } static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, - struct nameidata *nd) + struct nameidata *nd) { struct dentry *proc_dentry, *new, *parent; struct inode *inode; @@ -254,6 +254,8 @@ static ssize_t hppfs_read(struct file *file, char __user *buf, size_t count, int err; if (hppfs->contents != NULL) { + int rem; + if (*ppos >= hppfs->len) return 0; @@ -267,8 +269,10 @@ static ssize_t hppfs_read(struct file *file, char __user *buf, size_t count, if (off + count > hppfs->len) count = hppfs->len - off; - copy_to_user(buf, &data->contents[off], count); - *ppos += count; + rem = copy_to_user(buf, &data->contents[off], count); + *ppos += count - rem; + if (rem > 0) + return -EFAULT; } else if (hppfs->host_fd != -1) { err = os_seek_file(hppfs->host_fd, *ppos); if (err) { @@ -285,21 +289,15 @@ static ssize_t hppfs_read(struct file *file, char __user *buf, size_t count, return count; } -static ssize_t hppfs_write(struct file *file, const char __user *buf, size_t len, - loff_t *ppos) +static ssize_t hppfs_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) { struct hppfs_private *data = file->private_data; struct file *proc_file = data->proc_file; ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *); - int err; write = proc_file->f_path.dentry->d_inode->i_fop->write; - - proc_file->f_pos = file->f_pos; - err = (*write)(proc_file, buf, len, &proc_file->f_pos); - file->f_pos = proc_file->f_pos; - - return err; + return (*write)(proc_file, buf, len, ppos); } static int open_host_sock(char *host_file, int *filter_out) @@ -357,7 +355,7 @@ static struct hppfs_data *hppfs_get_data(int fd, int filter, if (filter) { while ((n = read_proc(proc_file, data->contents, - sizeof(data->contents), NULL, 0)) > 0) + sizeof(data->contents), NULL, 0)) > 0) os_write_file(fd, data->contents, n); err = os_shutdown_socket(fd, 0, 1); if (err) { @@ -429,8 +427,8 @@ static int file_mode(int fmode) static int hppfs_open(struct inode *inode, struct file *file) { struct hppfs_private *data; - struct dentry *proc_dentry; struct vfsmount *proc_mnt; + struct dentry *proc_dentry; char *host_file; int err, fd, type, filter; @@ -492,8 +490,8 @@ static int hppfs_open(struct inode *inode, struct file *file) static int hppfs_dir_open(struct inode *inode, struct file *file) { struct hppfs_private *data; - struct dentry *proc_dentry; struct vfsmount *proc_mnt; + struct dentry *proc_dentry; int err; err = -ENOMEM; @@ -620,6 +618,9 @@ static struct inode *hppfs_alloc_inode(struct super_block *sb) void hppfs_delete_inode(struct inode *ino) { + dput(HPPFS_I(ino)->proc_dentry); + mntput(ino->i_sb->s_fs_info); + clear_inode(ino); } @@ -628,69 +629,46 @@ static void hppfs_destroy_inode(struct inode *inode) kfree(HPPFS_I(inode)); } -static void hppfs_put_super(struct super_block *sb) -{ - mntput(sb->s_fs_info); -} - static const struct super_operations hppfs_sbops = { .alloc_inode = hppfs_alloc_inode, .destroy_inode = hppfs_destroy_inode, .delete_inode = hppfs_delete_inode, .statfs = hppfs_statfs, - .put_super = hppfs_put_super, }; static int hppfs_readlink(struct dentry *dentry, char __user *buffer, int buflen) { - struct file *proc_file; struct dentry *proc_dentry; - struct vfsmount *proc_mnt; - int ret; proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; - proc_mnt = dentry->d_sb->s_fs_info; - - proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), O_RDONLY); - if (IS_ERR(proc_file)) - return PTR_ERR(proc_file); - - ret = proc_dentry->d_inode->i_op->readlink(proc_dentry, buffer, buflen); - - fput(proc_file); - - return ret; + return proc_dentry->d_inode->i_op->readlink(proc_dentry, buffer, + buflen); } -static void* hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) +static void *hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) { - struct file *proc_file; struct dentry *proc_dentry; - struct vfsmount *proc_mnt; - void *ret; proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; - proc_mnt = dentry->d_sb->s_fs_info; - - proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), O_RDONLY); - if (IS_ERR(proc_file)) - return proc_file; - - ret = proc_dentry->d_inode->i_op->follow_link(proc_dentry, nd); - fput(proc_file); + return proc_dentry->d_inode->i_op->follow_link(proc_dentry, nd); +} - return ret; +int hppfs_permission(struct inode *inode, int mask, struct nameidata *nd) +{ + return generic_permission(inode, mask, NULL); } static const struct inode_operations hppfs_dir_iops = { .lookup = hppfs_lookup, + .permission = hppfs_permission, }; static const struct inode_operations hppfs_link_iops = { .readlink = hppfs_readlink, .follow_link = hppfs_follow_link, + .permission = hppfs_permission, }; static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) @@ -712,7 +690,7 @@ static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) inode->i_fop = &hppfs_file_fops; } - HPPFS_I(inode)->proc_dentry = dentry; + HPPFS_I(inode)->proc_dentry = dget(dentry); inode->i_uid = proc_ino->i_uid; inode->i_gid = proc_ino->i_gid; @@ -725,7 +703,7 @@ static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) inode->i_size = proc_ino->i_size; inode->i_blocks = proc_ino->i_blocks; - return 0; + return inode; } static int hppfs_fill_super(struct super_block *sb, void *d, int silent) -- cgit v1.1 From 46d7b522ebf486edbd096965d534cc6465e9e309 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:50 -0700 Subject: uml: move hppfs_kern.c to hppfs.c There's no reason for the _kern in hppfs_kern.c, so move it to hppfs.c. Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hppfs/Makefile | 6 +- fs/hppfs/hppfs.c | 771 ++++++++++++++++++++++++++++++++++++++++++++++++++ fs/hppfs/hppfs_kern.c | 771 -------------------------------------------------- 3 files changed, 774 insertions(+), 774 deletions(-) create mode 100644 fs/hppfs/hppfs.c delete mode 100644 fs/hppfs/hppfs_kern.c diff --git a/fs/hppfs/Makefile b/fs/hppfs/Makefile index 6890433..8a1f5034 100644 --- a/fs/hppfs/Makefile +++ b/fs/hppfs/Makefile @@ -1,9 +1,9 @@ # -# Copyright (C) 2002, 2003 Jeff Dike (jdike@karaya.com) +# Copyright (C) 2002 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) # Licensed under the GPL # -hppfs-objs := hppfs_kern.o +hppfs-objs := hppfs.o obj-y = -obj-$(CONFIG_HPPFS) += hppfs.o +obj-$(CONFIG_HPPFS) += $(hppfs-objs) diff --git a/fs/hppfs/hppfs.c b/fs/hppfs/hppfs.c new file mode 100644 index 0000000..65077aa --- /dev/null +++ b/fs/hppfs/hppfs.c @@ -0,0 +1,771 @@ +/* + * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Licensed under the GPL + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "os.h" + +static struct inode *get_inode(struct super_block *, struct dentry *); + +struct hppfs_data { + struct list_head list; + char contents[PAGE_SIZE - sizeof(struct list_head)]; +}; + +struct hppfs_private { + struct file *proc_file; + int host_fd; + loff_t len; + struct hppfs_data *contents; +}; + +struct hppfs_inode_info { + struct dentry *proc_dentry; + struct inode vfs_inode; +}; + +static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode) +{ + return container_of(inode, struct hppfs_inode_info, vfs_inode); +} + +#define HPPFS_SUPER_MAGIC 0xb00000ee + +static const struct super_operations hppfs_sbops; + +static int is_pid(struct dentry *dentry) +{ + struct super_block *sb; + int i; + + sb = dentry->d_sb; + if (dentry->d_parent != sb->s_root) + return 0; + + for (i = 0; i < dentry->d_name.len; i++) { + if (!isdigit(dentry->d_name.name[i])) + return 0; + } + return 1; +} + +static char *dentry_name(struct dentry *dentry, int extra) +{ + struct dentry *parent; + char *root, *name; + const char *seg_name; + int len, seg_len; + + len = 0; + parent = dentry; + while (parent->d_parent != parent) { + if (is_pid(parent)) + len += strlen("pid") + 1; + else len += parent->d_name.len + 1; + parent = parent->d_parent; + } + + root = "proc"; + len += strlen(root); + name = kmalloc(len + extra + 1, GFP_KERNEL); + if (name == NULL) + return NULL; + + name[len] = '\0'; + parent = dentry; + while (parent->d_parent != parent) { + if (is_pid(parent)) { + seg_name = "pid"; + seg_len = strlen("pid"); + } + else { + seg_name = parent->d_name.name; + seg_len = parent->d_name.len; + } + + len -= seg_len + 1; + name[len] = '/'; + strncpy(&name[len + 1], seg_name, seg_len); + parent = parent->d_parent; + } + strncpy(name, root, strlen(root)); + return name; +} + +static int file_removed(struct dentry *dentry, const char *file) +{ + char *host_file; + int extra, fd; + + extra = 0; + if (file != NULL) + extra += strlen(file) + 1; + + host_file = dentry_name(dentry, extra + strlen("/remove")); + if (host_file == NULL) { + printk(KERN_ERR "file_removed : allocation failed\n"); + return -ENOMEM; + } + + if (file != NULL) { + strcat(host_file, "/"); + strcat(host_file, file); + } + strcat(host_file, "/remove"); + + fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); + kfree(host_file); + if (fd > 0) { + os_close_file(fd); + return 1; + } + return 0; +} + +static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, + struct nameidata *nd) +{ + struct dentry *proc_dentry, *new, *parent; + struct inode *inode; + int err, deleted; + + deleted = file_removed(dentry, NULL); + if (deleted < 0) + return ERR_PTR(deleted); + else if (deleted) + return ERR_PTR(-ENOENT); + + err = -ENOMEM; + parent = HPPFS_I(ino)->proc_dentry; + mutex_lock(&parent->d_inode->i_mutex); + proc_dentry = d_lookup(parent, &dentry->d_name); + if (proc_dentry == NULL) { + proc_dentry = d_alloc(parent, &dentry->d_name); + if (proc_dentry == NULL) { + mutex_unlock(&parent->d_inode->i_mutex); + goto out; + } + new = (*parent->d_inode->i_op->lookup)(parent->d_inode, + proc_dentry, NULL); + if (new) { + dput(proc_dentry); + proc_dentry = new; + } + } + mutex_unlock(&parent->d_inode->i_mutex); + + if (IS_ERR(proc_dentry)) + return proc_dentry; + + err = -ENOMEM; + inode = get_inode(ino->i_sb, proc_dentry); + if (!inode) + goto out_dput; + + d_add(dentry, inode); + return NULL; + + out_dput: + dput(proc_dentry); + out: + return ERR_PTR(err); +} + +static const struct inode_operations hppfs_file_iops = { +}; + +static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count, + loff_t *ppos, int is_user) +{ + ssize_t (*read)(struct file *, char __user *, size_t, loff_t *); + ssize_t n; + + read = file->f_path.dentry->d_inode->i_fop->read; + + if (!is_user) + set_fs(KERNEL_DS); + + n = (*read)(file, buf, count, &file->f_pos); + + if (!is_user) + set_fs(USER_DS); + + if (ppos) + *ppos = file->f_pos; + return n; +} + +static ssize_t hppfs_read_file(int fd, char __user *buf, ssize_t count) +{ + ssize_t n; + int cur, err; + char *new_buf; + + n = -ENOMEM; + new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); + if (new_buf == NULL) { + printk(KERN_ERR "hppfs_read_file : kmalloc failed\n"); + goto out; + } + n = 0; + while (count > 0) { + cur = min_t(ssize_t, count, PAGE_SIZE); + err = os_read_file(fd, new_buf, cur); + if (err < 0) { + printk(KERN_ERR "hppfs_read : read failed, " + "errno = %d\n", err); + n = err; + goto out_free; + } else if (err == 0) + break; + + if (copy_to_user(buf, new_buf, err)) { + n = -EFAULT; + goto out_free; + } + n += err; + count -= err; + } + out_free: + kfree(new_buf); + out: + return n; +} + +static ssize_t hppfs_read(struct file *file, char __user *buf, size_t count, + loff_t *ppos) +{ + struct hppfs_private *hppfs = file->private_data; + struct hppfs_data *data; + loff_t off; + int err; + + if (hppfs->contents != NULL) { + int rem; + + if (*ppos >= hppfs->len) + return 0; + + data = hppfs->contents; + off = *ppos; + while (off >= sizeof(data->contents)) { + data = list_entry(data->list.next, struct hppfs_data, + list); + off -= sizeof(data->contents); + } + + if (off + count > hppfs->len) + count = hppfs->len - off; + rem = copy_to_user(buf, &data->contents[off], count); + *ppos += count - rem; + if (rem > 0) + return -EFAULT; + } else if (hppfs->host_fd != -1) { + err = os_seek_file(hppfs->host_fd, *ppos); + if (err) { + printk(KERN_ERR "hppfs_read : seek failed, " + "errno = %d\n", err); + return err; + } + count = hppfs_read_file(hppfs->host_fd, buf, count); + if (count > 0) + *ppos += count; + } + else count = read_proc(hppfs->proc_file, buf, count, ppos, 1); + + return count; +} + +static ssize_t hppfs_write(struct file *file, const char __user *buf, + size_t len, loff_t *ppos) +{ + struct hppfs_private *data = file->private_data; + struct file *proc_file = data->proc_file; + ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *); + + write = proc_file->f_path.dentry->d_inode->i_fop->write; + return (*write)(proc_file, buf, len, ppos); +} + +static int open_host_sock(char *host_file, int *filter_out) +{ + char *end; + int fd; + + end = &host_file[strlen(host_file)]; + strcpy(end, "/rw"); + *filter_out = 1; + fd = os_connect_socket(host_file); + if (fd > 0) + return fd; + + strcpy(end, "/r"); + *filter_out = 0; + fd = os_connect_socket(host_file); + return fd; +} + +static void free_contents(struct hppfs_data *head) +{ + struct hppfs_data *data; + struct list_head *ele, *next; + + if (head == NULL) + return; + + list_for_each_safe(ele, next, &head->list) { + data = list_entry(ele, struct hppfs_data, list); + kfree(data); + } + kfree(head); +} + +static struct hppfs_data *hppfs_get_data(int fd, int filter, + struct file *proc_file, + struct file *hppfs_file, + loff_t *size_out) +{ + struct hppfs_data *data, *new, *head; + int n, err; + + err = -ENOMEM; + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (data == NULL) { + printk(KERN_ERR "hppfs_get_data : head allocation failed\n"); + goto failed; + } + + INIT_LIST_HEAD(&data->list); + + head = data; + *size_out = 0; + + if (filter) { + while ((n = read_proc(proc_file, data->contents, + sizeof(data->contents), NULL, 0)) > 0) + os_write_file(fd, data->contents, n); + err = os_shutdown_socket(fd, 0, 1); + if (err) { + printk(KERN_ERR "hppfs_get_data : failed to shut down " + "socket\n"); + goto failed_free; + } + } + while (1) { + n = os_read_file(fd, data->contents, sizeof(data->contents)); + if (n < 0) { + err = n; + printk(KERN_ERR "hppfs_get_data : read failed, " + "errno = %d\n", err); + goto failed_free; + } else if (n == 0) + break; + + *size_out += n; + + if (n < sizeof(data->contents)) + break; + + new = kmalloc(sizeof(*data), GFP_KERNEL); + if (new == 0) { + printk(KERN_ERR "hppfs_get_data : data allocation " + "failed\n"); + err = -ENOMEM; + goto failed_free; + } + + INIT_LIST_HEAD(&new->list); + list_add(&new->list, &data->list); + data = new; + } + return head; + + failed_free: + free_contents(head); + failed: + return ERR_PTR(err); +} + +static struct hppfs_private *hppfs_data(void) +{ + struct hppfs_private *data; + + data = kmalloc(sizeof(*data), GFP_KERNEL); + if (data == NULL) + return data; + + *data = ((struct hppfs_private ) { .host_fd = -1, + .len = -1, + .contents = NULL } ); + return data; +} + +static int file_mode(int fmode) +{ + if (fmode == (FMODE_READ | FMODE_WRITE)) + return O_RDWR; + if (fmode == FMODE_READ) + return O_RDONLY; + if (fmode == FMODE_WRITE) + return O_WRONLY; + return 0; +} + +static int hppfs_open(struct inode *inode, struct file *file) +{ + struct hppfs_private *data; + struct vfsmount *proc_mnt; + struct dentry *proc_dentry; + char *host_file; + int err, fd, type, filter; + + err = -ENOMEM; + data = hppfs_data(); + if (data == NULL) + goto out; + + host_file = dentry_name(file->f_path.dentry, strlen("/rw")); + if (host_file == NULL) + goto out_free2; + + proc_dentry = HPPFS_I(inode)->proc_dentry; + proc_mnt = inode->i_sb->s_fs_info; + + /* XXX This isn't closed anywhere */ + data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), + file_mode(file->f_mode)); + err = PTR_ERR(data->proc_file); + if (IS_ERR(data->proc_file)) + goto out_free1; + + type = os_file_type(host_file); + if (type == OS_TYPE_FILE) { + fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); + if (fd >= 0) + data->host_fd = fd; + else + printk(KERN_ERR "hppfs_open : failed to open '%s', " + "errno = %d\n", host_file, -fd); + + data->contents = NULL; + } else if (type == OS_TYPE_DIR) { + fd = open_host_sock(host_file, &filter); + if (fd > 0) { + data->contents = hppfs_get_data(fd, filter, + data->proc_file, + file, &data->len); + if (!IS_ERR(data->contents)) + data->host_fd = fd; + } else + printk(KERN_ERR "hppfs_open : failed to open a socket " + "in '%s', errno = %d\n", host_file, -fd); + } + kfree(host_file); + + file->private_data = data; + return 0; + + out_free1: + kfree(host_file); + out_free2: + free_contents(data->contents); + kfree(data); + out: + return err; +} + +static int hppfs_dir_open(struct inode *inode, struct file *file) +{ + struct hppfs_private *data; + struct vfsmount *proc_mnt; + struct dentry *proc_dentry; + int err; + + err = -ENOMEM; + data = hppfs_data(); + if (data == NULL) + goto out; + + proc_dentry = HPPFS_I(inode)->proc_dentry; + proc_mnt = inode->i_sb->s_fs_info; + data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), + file_mode(file->f_mode)); + err = PTR_ERR(data->proc_file); + if (IS_ERR(data->proc_file)) + goto out_free; + + file->private_data = data; + return 0; + + out_free: + kfree(data); + out: + return err; +} + +static loff_t hppfs_llseek(struct file *file, loff_t off, int where) +{ + struct hppfs_private *data = file->private_data; + struct file *proc_file = data->proc_file; + loff_t (*llseek)(struct file *, loff_t, int); + loff_t ret; + + llseek = proc_file->f_path.dentry->d_inode->i_fop->llseek; + if (llseek != NULL) { + ret = (*llseek)(proc_file, off, where); + if (ret < 0) + return ret; + } + + return default_llseek(file, off, where); +} + +static const struct file_operations hppfs_file_fops = { + .owner = NULL, + .llseek = hppfs_llseek, + .read = hppfs_read, + .write = hppfs_write, + .open = hppfs_open, +}; + +struct hppfs_dirent { + void *vfs_dirent; + filldir_t filldir; + struct dentry *dentry; +}; + +static int hppfs_filldir(void *d, const char *name, int size, + loff_t offset, u64 inode, unsigned int type) +{ + struct hppfs_dirent *dirent = d; + + if (file_removed(dirent->dentry, name)) + return 0; + + return (*dirent->filldir)(dirent->vfs_dirent, name, size, offset, + inode, type); +} + +static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) +{ + struct hppfs_private *data = file->private_data; + struct file *proc_file = data->proc_file; + int (*readdir)(struct file *, void *, filldir_t); + struct hppfs_dirent dirent = ((struct hppfs_dirent) + { .vfs_dirent = ent, + .filldir = filldir, + .dentry = file->f_path.dentry + }); + int err; + + readdir = proc_file->f_path.dentry->d_inode->i_fop->readdir; + + proc_file->f_pos = file->f_pos; + err = (*readdir)(proc_file, &dirent, hppfs_filldir); + file->f_pos = proc_file->f_pos; + + return err; +} + +static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync) +{ + return 0; +} + +static const struct file_operations hppfs_dir_fops = { + .owner = NULL, + .readdir = hppfs_readdir, + .open = hppfs_dir_open, + .fsync = hppfs_fsync, +}; + +static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf) +{ + sf->f_blocks = 0; + sf->f_bfree = 0; + sf->f_bavail = 0; + sf->f_files = 0; + sf->f_ffree = 0; + sf->f_type = HPPFS_SUPER_MAGIC; + return 0; +} + +static struct inode *hppfs_alloc_inode(struct super_block *sb) +{ + struct hppfs_inode_info *hi; + + hi = kmalloc(sizeof(*hi), GFP_KERNEL); + if (!hi) + return NULL; + + hi->proc_dentry = NULL; + inode_init_once(&hi->vfs_inode); + return &hi->vfs_inode; +} + +void hppfs_delete_inode(struct inode *ino) +{ + dput(HPPFS_I(ino)->proc_dentry); + mntput(ino->i_sb->s_fs_info); + + clear_inode(ino); +} + +static void hppfs_destroy_inode(struct inode *inode) +{ + kfree(HPPFS_I(inode)); +} + +static const struct super_operations hppfs_sbops = { + .alloc_inode = hppfs_alloc_inode, + .destroy_inode = hppfs_destroy_inode, + .delete_inode = hppfs_delete_inode, + .statfs = hppfs_statfs, +}; + +static int hppfs_readlink(struct dentry *dentry, char __user *buffer, + int buflen) +{ + struct dentry *proc_dentry; + + proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; + return proc_dentry->d_inode->i_op->readlink(proc_dentry, buffer, + buflen); +} + +static void *hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) +{ + struct dentry *proc_dentry; + + proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; + + return proc_dentry->d_inode->i_op->follow_link(proc_dentry, nd); +} + +int hppfs_permission(struct inode *inode, int mask, struct nameidata *nd) +{ + return generic_permission(inode, mask, NULL); +} + +static const struct inode_operations hppfs_dir_iops = { + .lookup = hppfs_lookup, + .permission = hppfs_permission, +}; + +static const struct inode_operations hppfs_link_iops = { + .readlink = hppfs_readlink, + .follow_link = hppfs_follow_link, + .permission = hppfs_permission, +}; + +static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) +{ + struct inode *proc_ino = dentry->d_inode; + struct inode *inode = new_inode(sb); + + if (!inode) + return ERR_PTR(-ENOMEM); + + if (S_ISDIR(dentry->d_inode->i_mode)) { + inode->i_op = &hppfs_dir_iops; + inode->i_fop = &hppfs_dir_fops; + } else if (S_ISLNK(dentry->d_inode->i_mode)) { + inode->i_op = &hppfs_link_iops; + inode->i_fop = &hppfs_file_fops; + } else { + inode->i_op = &hppfs_file_iops; + inode->i_fop = &hppfs_file_fops; + } + + HPPFS_I(inode)->proc_dentry = dget(dentry); + + inode->i_uid = proc_ino->i_uid; + inode->i_gid = proc_ino->i_gid; + inode->i_atime = proc_ino->i_atime; + inode->i_mtime = proc_ino->i_mtime; + inode->i_ctime = proc_ino->i_ctime; + inode->i_ino = proc_ino->i_ino; + inode->i_mode = proc_ino->i_mode; + inode->i_nlink = proc_ino->i_nlink; + inode->i_size = proc_ino->i_size; + inode->i_blocks = proc_ino->i_blocks; + + return inode; +} + +static int hppfs_fill_super(struct super_block *sb, void *d, int silent) +{ + struct inode *root_inode; + struct vfsmount *proc_mnt; + int err = -ENOENT; + + proc_mnt = do_kern_mount("proc", 0, "proc", NULL); + if (IS_ERR(proc_mnt)) + goto out; + + sb->s_blocksize = 1024; + sb->s_blocksize_bits = 10; + sb->s_magic = HPPFS_SUPER_MAGIC; + sb->s_op = &hppfs_sbops; + sb->s_fs_info = proc_mnt; + + err = -ENOMEM; + root_inode = get_inode(sb, proc_mnt->mnt_sb->s_root); + if (!root_inode) + goto out_mntput; + + sb->s_root = d_alloc_root(root_inode); + if (!sb->s_root) + goto out_iput; + + return 0; + + out_iput: + iput(root_inode); + out_mntput: + mntput(proc_mnt); + out: + return(err); +} + +static int hppfs_read_super(struct file_system_type *type, + int flags, const char *dev_name, + void *data, struct vfsmount *mnt) +{ + return get_sb_nodev(type, flags, data, hppfs_fill_super, mnt); +} + +static struct file_system_type hppfs_type = { + .owner = THIS_MODULE, + .name = "hppfs", + .get_sb = hppfs_read_super, + .kill_sb = kill_anon_super, + .fs_flags = 0, +}; + +static int __init init_hppfs(void) +{ + return register_filesystem(&hppfs_type); +} + +static void __exit exit_hppfs(void) +{ + unregister_filesystem(&hppfs_type); +} + +module_init(init_hppfs) +module_exit(exit_hppfs) +MODULE_LICENSE("GPL"); diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c deleted file mode 100644 index 65077aa..0000000 --- a/fs/hppfs/hppfs_kern.c +++ /dev/null @@ -1,771 +0,0 @@ -/* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) - * Licensed under the GPL - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "os.h" - -static struct inode *get_inode(struct super_block *, struct dentry *); - -struct hppfs_data { - struct list_head list; - char contents[PAGE_SIZE - sizeof(struct list_head)]; -}; - -struct hppfs_private { - struct file *proc_file; - int host_fd; - loff_t len; - struct hppfs_data *contents; -}; - -struct hppfs_inode_info { - struct dentry *proc_dentry; - struct inode vfs_inode; -}; - -static inline struct hppfs_inode_info *HPPFS_I(struct inode *inode) -{ - return container_of(inode, struct hppfs_inode_info, vfs_inode); -} - -#define HPPFS_SUPER_MAGIC 0xb00000ee - -static const struct super_operations hppfs_sbops; - -static int is_pid(struct dentry *dentry) -{ - struct super_block *sb; - int i; - - sb = dentry->d_sb; - if (dentry->d_parent != sb->s_root) - return 0; - - for (i = 0; i < dentry->d_name.len; i++) { - if (!isdigit(dentry->d_name.name[i])) - return 0; - } - return 1; -} - -static char *dentry_name(struct dentry *dentry, int extra) -{ - struct dentry *parent; - char *root, *name; - const char *seg_name; - int len, seg_len; - - len = 0; - parent = dentry; - while (parent->d_parent != parent) { - if (is_pid(parent)) - len += strlen("pid") + 1; - else len += parent->d_name.len + 1; - parent = parent->d_parent; - } - - root = "proc"; - len += strlen(root); - name = kmalloc(len + extra + 1, GFP_KERNEL); - if (name == NULL) - return NULL; - - name[len] = '\0'; - parent = dentry; - while (parent->d_parent != parent) { - if (is_pid(parent)) { - seg_name = "pid"; - seg_len = strlen("pid"); - } - else { - seg_name = parent->d_name.name; - seg_len = parent->d_name.len; - } - - len -= seg_len + 1; - name[len] = '/'; - strncpy(&name[len + 1], seg_name, seg_len); - parent = parent->d_parent; - } - strncpy(name, root, strlen(root)); - return name; -} - -static int file_removed(struct dentry *dentry, const char *file) -{ - char *host_file; - int extra, fd; - - extra = 0; - if (file != NULL) - extra += strlen(file) + 1; - - host_file = dentry_name(dentry, extra + strlen("/remove")); - if (host_file == NULL) { - printk(KERN_ERR "file_removed : allocation failed\n"); - return -ENOMEM; - } - - if (file != NULL) { - strcat(host_file, "/"); - strcat(host_file, file); - } - strcat(host_file, "/remove"); - - fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); - kfree(host_file); - if (fd > 0) { - os_close_file(fd); - return 1; - } - return 0; -} - -static struct dentry *hppfs_lookup(struct inode *ino, struct dentry *dentry, - struct nameidata *nd) -{ - struct dentry *proc_dentry, *new, *parent; - struct inode *inode; - int err, deleted; - - deleted = file_removed(dentry, NULL); - if (deleted < 0) - return ERR_PTR(deleted); - else if (deleted) - return ERR_PTR(-ENOENT); - - err = -ENOMEM; - parent = HPPFS_I(ino)->proc_dentry; - mutex_lock(&parent->d_inode->i_mutex); - proc_dentry = d_lookup(parent, &dentry->d_name); - if (proc_dentry == NULL) { - proc_dentry = d_alloc(parent, &dentry->d_name); - if (proc_dentry == NULL) { - mutex_unlock(&parent->d_inode->i_mutex); - goto out; - } - new = (*parent->d_inode->i_op->lookup)(parent->d_inode, - proc_dentry, NULL); - if (new) { - dput(proc_dentry); - proc_dentry = new; - } - } - mutex_unlock(&parent->d_inode->i_mutex); - - if (IS_ERR(proc_dentry)) - return proc_dentry; - - err = -ENOMEM; - inode = get_inode(ino->i_sb, proc_dentry); - if (!inode) - goto out_dput; - - d_add(dentry, inode); - return NULL; - - out_dput: - dput(proc_dentry); - out: - return ERR_PTR(err); -} - -static const struct inode_operations hppfs_file_iops = { -}; - -static ssize_t read_proc(struct file *file, char __user *buf, ssize_t count, - loff_t *ppos, int is_user) -{ - ssize_t (*read)(struct file *, char __user *, size_t, loff_t *); - ssize_t n; - - read = file->f_path.dentry->d_inode->i_fop->read; - - if (!is_user) - set_fs(KERNEL_DS); - - n = (*read)(file, buf, count, &file->f_pos); - - if (!is_user) - set_fs(USER_DS); - - if (ppos) - *ppos = file->f_pos; - return n; -} - -static ssize_t hppfs_read_file(int fd, char __user *buf, ssize_t count) -{ - ssize_t n; - int cur, err; - char *new_buf; - - n = -ENOMEM; - new_buf = kmalloc(PAGE_SIZE, GFP_KERNEL); - if (new_buf == NULL) { - printk(KERN_ERR "hppfs_read_file : kmalloc failed\n"); - goto out; - } - n = 0; - while (count > 0) { - cur = min_t(ssize_t, count, PAGE_SIZE); - err = os_read_file(fd, new_buf, cur); - if (err < 0) { - printk(KERN_ERR "hppfs_read : read failed, " - "errno = %d\n", err); - n = err; - goto out_free; - } else if (err == 0) - break; - - if (copy_to_user(buf, new_buf, err)) { - n = -EFAULT; - goto out_free; - } - n += err; - count -= err; - } - out_free: - kfree(new_buf); - out: - return n; -} - -static ssize_t hppfs_read(struct file *file, char __user *buf, size_t count, - loff_t *ppos) -{ - struct hppfs_private *hppfs = file->private_data; - struct hppfs_data *data; - loff_t off; - int err; - - if (hppfs->contents != NULL) { - int rem; - - if (*ppos >= hppfs->len) - return 0; - - data = hppfs->contents; - off = *ppos; - while (off >= sizeof(data->contents)) { - data = list_entry(data->list.next, struct hppfs_data, - list); - off -= sizeof(data->contents); - } - - if (off + count > hppfs->len) - count = hppfs->len - off; - rem = copy_to_user(buf, &data->contents[off], count); - *ppos += count - rem; - if (rem > 0) - return -EFAULT; - } else if (hppfs->host_fd != -1) { - err = os_seek_file(hppfs->host_fd, *ppos); - if (err) { - printk(KERN_ERR "hppfs_read : seek failed, " - "errno = %d\n", err); - return err; - } - count = hppfs_read_file(hppfs->host_fd, buf, count); - if (count > 0) - *ppos += count; - } - else count = read_proc(hppfs->proc_file, buf, count, ppos, 1); - - return count; -} - -static ssize_t hppfs_write(struct file *file, const char __user *buf, - size_t len, loff_t *ppos) -{ - struct hppfs_private *data = file->private_data; - struct file *proc_file = data->proc_file; - ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *); - - write = proc_file->f_path.dentry->d_inode->i_fop->write; - return (*write)(proc_file, buf, len, ppos); -} - -static int open_host_sock(char *host_file, int *filter_out) -{ - char *end; - int fd; - - end = &host_file[strlen(host_file)]; - strcpy(end, "/rw"); - *filter_out = 1; - fd = os_connect_socket(host_file); - if (fd > 0) - return fd; - - strcpy(end, "/r"); - *filter_out = 0; - fd = os_connect_socket(host_file); - return fd; -} - -static void free_contents(struct hppfs_data *head) -{ - struct hppfs_data *data; - struct list_head *ele, *next; - - if (head == NULL) - return; - - list_for_each_safe(ele, next, &head->list) { - data = list_entry(ele, struct hppfs_data, list); - kfree(data); - } - kfree(head); -} - -static struct hppfs_data *hppfs_get_data(int fd, int filter, - struct file *proc_file, - struct file *hppfs_file, - loff_t *size_out) -{ - struct hppfs_data *data, *new, *head; - int n, err; - - err = -ENOMEM; - data = kmalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) { - printk(KERN_ERR "hppfs_get_data : head allocation failed\n"); - goto failed; - } - - INIT_LIST_HEAD(&data->list); - - head = data; - *size_out = 0; - - if (filter) { - while ((n = read_proc(proc_file, data->contents, - sizeof(data->contents), NULL, 0)) > 0) - os_write_file(fd, data->contents, n); - err = os_shutdown_socket(fd, 0, 1); - if (err) { - printk(KERN_ERR "hppfs_get_data : failed to shut down " - "socket\n"); - goto failed_free; - } - } - while (1) { - n = os_read_file(fd, data->contents, sizeof(data->contents)); - if (n < 0) { - err = n; - printk(KERN_ERR "hppfs_get_data : read failed, " - "errno = %d\n", err); - goto failed_free; - } else if (n == 0) - break; - - *size_out += n; - - if (n < sizeof(data->contents)) - break; - - new = kmalloc(sizeof(*data), GFP_KERNEL); - if (new == 0) { - printk(KERN_ERR "hppfs_get_data : data allocation " - "failed\n"); - err = -ENOMEM; - goto failed_free; - } - - INIT_LIST_HEAD(&new->list); - list_add(&new->list, &data->list); - data = new; - } - return head; - - failed_free: - free_contents(head); - failed: - return ERR_PTR(err); -} - -static struct hppfs_private *hppfs_data(void) -{ - struct hppfs_private *data; - - data = kmalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) - return data; - - *data = ((struct hppfs_private ) { .host_fd = -1, - .len = -1, - .contents = NULL } ); - return data; -} - -static int file_mode(int fmode) -{ - if (fmode == (FMODE_READ | FMODE_WRITE)) - return O_RDWR; - if (fmode == FMODE_READ) - return O_RDONLY; - if (fmode == FMODE_WRITE) - return O_WRONLY; - return 0; -} - -static int hppfs_open(struct inode *inode, struct file *file) -{ - struct hppfs_private *data; - struct vfsmount *proc_mnt; - struct dentry *proc_dentry; - char *host_file; - int err, fd, type, filter; - - err = -ENOMEM; - data = hppfs_data(); - if (data == NULL) - goto out; - - host_file = dentry_name(file->f_path.dentry, strlen("/rw")); - if (host_file == NULL) - goto out_free2; - - proc_dentry = HPPFS_I(inode)->proc_dentry; - proc_mnt = inode->i_sb->s_fs_info; - - /* XXX This isn't closed anywhere */ - data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), - file_mode(file->f_mode)); - err = PTR_ERR(data->proc_file); - if (IS_ERR(data->proc_file)) - goto out_free1; - - type = os_file_type(host_file); - if (type == OS_TYPE_FILE) { - fd = os_open_file(host_file, of_read(OPENFLAGS()), 0); - if (fd >= 0) - data->host_fd = fd; - else - printk(KERN_ERR "hppfs_open : failed to open '%s', " - "errno = %d\n", host_file, -fd); - - data->contents = NULL; - } else if (type == OS_TYPE_DIR) { - fd = open_host_sock(host_file, &filter); - if (fd > 0) { - data->contents = hppfs_get_data(fd, filter, - data->proc_file, - file, &data->len); - if (!IS_ERR(data->contents)) - data->host_fd = fd; - } else - printk(KERN_ERR "hppfs_open : failed to open a socket " - "in '%s', errno = %d\n", host_file, -fd); - } - kfree(host_file); - - file->private_data = data; - return 0; - - out_free1: - kfree(host_file); - out_free2: - free_contents(data->contents); - kfree(data); - out: - return err; -} - -static int hppfs_dir_open(struct inode *inode, struct file *file) -{ - struct hppfs_private *data; - struct vfsmount *proc_mnt; - struct dentry *proc_dentry; - int err; - - err = -ENOMEM; - data = hppfs_data(); - if (data == NULL) - goto out; - - proc_dentry = HPPFS_I(inode)->proc_dentry; - proc_mnt = inode->i_sb->s_fs_info; - data->proc_file = dentry_open(dget(proc_dentry), mntget(proc_mnt), - file_mode(file->f_mode)); - err = PTR_ERR(data->proc_file); - if (IS_ERR(data->proc_file)) - goto out_free; - - file->private_data = data; - return 0; - - out_free: - kfree(data); - out: - return err; -} - -static loff_t hppfs_llseek(struct file *file, loff_t off, int where) -{ - struct hppfs_private *data = file->private_data; - struct file *proc_file = data->proc_file; - loff_t (*llseek)(struct file *, loff_t, int); - loff_t ret; - - llseek = proc_file->f_path.dentry->d_inode->i_fop->llseek; - if (llseek != NULL) { - ret = (*llseek)(proc_file, off, where); - if (ret < 0) - return ret; - } - - return default_llseek(file, off, where); -} - -static const struct file_operations hppfs_file_fops = { - .owner = NULL, - .llseek = hppfs_llseek, - .read = hppfs_read, - .write = hppfs_write, - .open = hppfs_open, -}; - -struct hppfs_dirent { - void *vfs_dirent; - filldir_t filldir; - struct dentry *dentry; -}; - -static int hppfs_filldir(void *d, const char *name, int size, - loff_t offset, u64 inode, unsigned int type) -{ - struct hppfs_dirent *dirent = d; - - if (file_removed(dirent->dentry, name)) - return 0; - - return (*dirent->filldir)(dirent->vfs_dirent, name, size, offset, - inode, type); -} - -static int hppfs_readdir(struct file *file, void *ent, filldir_t filldir) -{ - struct hppfs_private *data = file->private_data; - struct file *proc_file = data->proc_file; - int (*readdir)(struct file *, void *, filldir_t); - struct hppfs_dirent dirent = ((struct hppfs_dirent) - { .vfs_dirent = ent, - .filldir = filldir, - .dentry = file->f_path.dentry - }); - int err; - - readdir = proc_file->f_path.dentry->d_inode->i_fop->readdir; - - proc_file->f_pos = file->f_pos; - err = (*readdir)(proc_file, &dirent, hppfs_filldir); - file->f_pos = proc_file->f_pos; - - return err; -} - -static int hppfs_fsync(struct file *file, struct dentry *dentry, int datasync) -{ - return 0; -} - -static const struct file_operations hppfs_dir_fops = { - .owner = NULL, - .readdir = hppfs_readdir, - .open = hppfs_dir_open, - .fsync = hppfs_fsync, -}; - -static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf) -{ - sf->f_blocks = 0; - sf->f_bfree = 0; - sf->f_bavail = 0; - sf->f_files = 0; - sf->f_ffree = 0; - sf->f_type = HPPFS_SUPER_MAGIC; - return 0; -} - -static struct inode *hppfs_alloc_inode(struct super_block *sb) -{ - struct hppfs_inode_info *hi; - - hi = kmalloc(sizeof(*hi), GFP_KERNEL); - if (!hi) - return NULL; - - hi->proc_dentry = NULL; - inode_init_once(&hi->vfs_inode); - return &hi->vfs_inode; -} - -void hppfs_delete_inode(struct inode *ino) -{ - dput(HPPFS_I(ino)->proc_dentry); - mntput(ino->i_sb->s_fs_info); - - clear_inode(ino); -} - -static void hppfs_destroy_inode(struct inode *inode) -{ - kfree(HPPFS_I(inode)); -} - -static const struct super_operations hppfs_sbops = { - .alloc_inode = hppfs_alloc_inode, - .destroy_inode = hppfs_destroy_inode, - .delete_inode = hppfs_delete_inode, - .statfs = hppfs_statfs, -}; - -static int hppfs_readlink(struct dentry *dentry, char __user *buffer, - int buflen) -{ - struct dentry *proc_dentry; - - proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; - return proc_dentry->d_inode->i_op->readlink(proc_dentry, buffer, - buflen); -} - -static void *hppfs_follow_link(struct dentry *dentry, struct nameidata *nd) -{ - struct dentry *proc_dentry; - - proc_dentry = HPPFS_I(dentry->d_inode)->proc_dentry; - - return proc_dentry->d_inode->i_op->follow_link(proc_dentry, nd); -} - -int hppfs_permission(struct inode *inode, int mask, struct nameidata *nd) -{ - return generic_permission(inode, mask, NULL); -} - -static const struct inode_operations hppfs_dir_iops = { - .lookup = hppfs_lookup, - .permission = hppfs_permission, -}; - -static const struct inode_operations hppfs_link_iops = { - .readlink = hppfs_readlink, - .follow_link = hppfs_follow_link, - .permission = hppfs_permission, -}; - -static struct inode *get_inode(struct super_block *sb, struct dentry *dentry) -{ - struct inode *proc_ino = dentry->d_inode; - struct inode *inode = new_inode(sb); - - if (!inode) - return ERR_PTR(-ENOMEM); - - if (S_ISDIR(dentry->d_inode->i_mode)) { - inode->i_op = &hppfs_dir_iops; - inode->i_fop = &hppfs_dir_fops; - } else if (S_ISLNK(dentry->d_inode->i_mode)) { - inode->i_op = &hppfs_link_iops; - inode->i_fop = &hppfs_file_fops; - } else { - inode->i_op = &hppfs_file_iops; - inode->i_fop = &hppfs_file_fops; - } - - HPPFS_I(inode)->proc_dentry = dget(dentry); - - inode->i_uid = proc_ino->i_uid; - inode->i_gid = proc_ino->i_gid; - inode->i_atime = proc_ino->i_atime; - inode->i_mtime = proc_ino->i_mtime; - inode->i_ctime = proc_ino->i_ctime; - inode->i_ino = proc_ino->i_ino; - inode->i_mode = proc_ino->i_mode; - inode->i_nlink = proc_ino->i_nlink; - inode->i_size = proc_ino->i_size; - inode->i_blocks = proc_ino->i_blocks; - - return inode; -} - -static int hppfs_fill_super(struct super_block *sb, void *d, int silent) -{ - struct inode *root_inode; - struct vfsmount *proc_mnt; - int err = -ENOENT; - - proc_mnt = do_kern_mount("proc", 0, "proc", NULL); - if (IS_ERR(proc_mnt)) - goto out; - - sb->s_blocksize = 1024; - sb->s_blocksize_bits = 10; - sb->s_magic = HPPFS_SUPER_MAGIC; - sb->s_op = &hppfs_sbops; - sb->s_fs_info = proc_mnt; - - err = -ENOMEM; - root_inode = get_inode(sb, proc_mnt->mnt_sb->s_root); - if (!root_inode) - goto out_mntput; - - sb->s_root = d_alloc_root(root_inode); - if (!sb->s_root) - goto out_iput; - - return 0; - - out_iput: - iput(root_inode); - out_mntput: - mntput(proc_mnt); - out: - return(err); -} - -static int hppfs_read_super(struct file_system_type *type, - int flags, const char *dev_name, - void *data, struct vfsmount *mnt) -{ - return get_sb_nodev(type, flags, data, hppfs_fill_super, mnt); -} - -static struct file_system_type hppfs_type = { - .owner = THIS_MODULE, - .name = "hppfs", - .get_sb = hppfs_read_super, - .kill_sb = kill_anon_super, - .fs_flags = 0, -}; - -static int __init init_hppfs(void) -{ - return register_filesystem(&hppfs_type); -} - -static void __exit exit_hppfs(void) -{ - unregister_filesystem(&hppfs_type); -} - -module_init(init_hppfs) -module_exit(exit_hppfs) -MODULE_LICENSE("GPL"); -- cgit v1.1 From 47906dd9e63ba1a8cb188e9e786c5928674fbbd3 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:50 -0700 Subject: uml: tidy ptrace interface Tidy the ptrace interface code. Removed a bunch of unused macros. Started converting register sets from arrays of longs to structures. Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/sysdep-i386/ptrace_user.h | 30 +---------------------------- arch/um/include/sysdep-x86_64/ptrace_user.h | 17 ++++------------ arch/um/os-Linux/sys-i386/registers.c | 5 +++-- arch/um/sys-i386/ptrace.c | 30 ++++++++++++++--------------- arch/um/sys-i386/user-offsets.c | 2 +- arch/um/sys-x86_64/user-offsets.c | 1 - 6 files changed, 23 insertions(+), 62 deletions(-) diff --git a/arch/um/include/sysdep-i386/ptrace_user.h b/arch/um/include/sysdep-i386/ptrace_user.h index 7565072..ef56247 100644 --- a/arch/um/include/sysdep-i386/ptrace_user.h +++ b/arch/um/include/sysdep-i386/ptrace_user.h @@ -41,38 +41,10 @@ #define PT_SP_OFFSET PT_OFFSET(UESP) #define PT_SP(regs) ((regs)[UESP]) -#define FP_SIZE ((HOST_XFP_SIZE > HOST_FP_SIZE) ? HOST_XFP_SIZE : HOST_FP_SIZE) +#define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE) #ifndef FRAME_SIZE #define FRAME_SIZE (17) #endif -#define FRAME_SIZE_OFFSET (FRAME_SIZE * sizeof(unsigned long)) - -#define FP_FRAME_SIZE (27) -#define FPX_FRAME_SIZE (128) - -#ifdef PTRACE_GETREGS -#define UM_HAVE_GETREGS -#endif - -#ifdef PTRACE_SETREGS -#define UM_HAVE_SETREGS -#endif - -#ifdef PTRACE_GETFPREGS -#define UM_HAVE_GETFPREGS -#endif - -#ifdef PTRACE_SETFPREGS -#define UM_HAVE_SETFPREGS -#endif - -#ifdef PTRACE_GETFPXREGS -#define UM_HAVE_GETFPXREGS -#endif - -#ifdef PTRACE_SETFPXREGS -#define UM_HAVE_SETFPXREGS -#endif #endif diff --git a/arch/um/include/sysdep-x86_64/ptrace_user.h b/arch/um/include/sysdep-x86_64/ptrace_user.h index 45c0bd8..4dbccdb 100644 --- a/arch/um/include/sysdep-x86_64/ptrace_user.h +++ b/arch/um/include/sysdep-x86_64/ptrace_user.h @@ -48,7 +48,8 @@ #define PT_ORIG_RAX_OFFSET (ORIG_RAX) #define PT_ORIG_RAX(regs) ((regs)[PT_INDEX(ORIG_RAX)]) -/* x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though +/* + * x86_64 FC3 doesn't define this in /usr/include/linux/ptrace.h even though * it's defined in the kernel's include/linux/ptrace.h. Additionally, use the * 2.4 name and value for 2.4 host compatibility. */ @@ -56,7 +57,8 @@ #define PTRACE_OLDSETOPTIONS 21 #endif -/* These are before the system call, so the system call number is RAX +/* + * These are before the system call, so the system call number is RAX * rather than ORIG_RAX, and arg4 is R10 rather than RCX */ #define REGS_SYSCALL_NR PT_INDEX(RAX) @@ -73,14 +75,3 @@ #define FP_SIZE (HOST_FP_SIZE) #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index b613473..c6183e7 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -5,6 +5,7 @@ */ #include +#include #include "kern_constants.h" #include "longjmp.h" #include "user.h" @@ -74,10 +75,10 @@ int put_fp_registers(int pid, unsigned long *regs) void arch_init_registers(int pid) { - unsigned long fpx_regs[HOST_XFP_SIZE]; + struct user_fxsr_struct fpx_regs; int err; - err = ptrace(PTRACE_GETFPXREGS, pid, 0, fpx_regs); + err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs); if (!err) return; diff --git a/arch/um/sys-i386/ptrace.c b/arch/um/sys-i386/ptrace.c index 6b44999..c9b1765 100644 --- a/arch/um/sys-i386/ptrace.c +++ b/arch/um/sys-i386/ptrace.c @@ -148,14 +148,13 @@ int peek_user(struct task_struct *child, long addr, long data) int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) { int err, n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_FP_SIZE]; + struct user_i387_struct fpregs; - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - err = save_fp_registers(userspace_pid[cpu], fpregs); + err = save_fp_registers(userspace_pid[cpu], (unsigned long *) &fpregs); if (err) return err; - n = copy_to_user(buf, fpregs, sizeof(fpregs)); + n = copy_to_user(buf, &fpregs, sizeof(fpregs)); if(n > 0) return -EFAULT; @@ -165,27 +164,26 @@ int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child) { int n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_FP_SIZE]; + struct user_i387_struct fpregs; - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - n = copy_from_user(fpregs, buf, sizeof(fpregs)); + n = copy_from_user(&fpregs, buf, sizeof(fpregs)); if (n > 0) return -EFAULT; - return restore_fp_registers(userspace_pid[cpu], fpregs); + return restore_fp_registers(userspace_pid[cpu], + (unsigned long *) &fpregs); } int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) { int err, n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_XFP_SIZE]; + struct user_fxsr_struct fpregs; - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - err = save_fpx_registers(userspace_pid[cpu], fpregs); + err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs); if (err) return err; - n = copy_to_user(buf, fpregs, sizeof(fpregs)); + n = copy_to_user(buf, &fpregs, sizeof(fpregs)); if(n > 0) return -EFAULT; @@ -195,14 +193,14 @@ int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child) { int n, cpu = ((struct thread_info *) child->stack)->cpu; - long fpregs[HOST_XFP_SIZE]; + struct user_fxsr_struct fpregs; - BUG_ON(sizeof(*buf) != sizeof(fpregs)); - n = copy_from_user(fpregs, buf, sizeof(fpregs)); + n = copy_from_user(&fpregs, buf, sizeof(fpregs)); if (n > 0) return -EFAULT; - return restore_fpx_registers(userspace_pid[cpu], fpregs); + return restore_fpx_registers(userspace_pid[cpu], + (unsigned long *) &fpregs); } long subarch_ptrace(struct task_struct *child, long request, long addr, diff --git a/arch/um/sys-i386/user-offsets.c b/arch/um/sys-i386/user-offsets.c index 39bd32b..5f883bf 100644 --- a/arch/um/sys-i386/user-offsets.c +++ b/arch/um/sys-i386/user-offsets.c @@ -22,7 +22,7 @@ void foo(void) OFFSET(HOST_SC_CR2, sigcontext, cr2); DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct)); - DEFINE_LONGS(HOST_XFP_SIZE, sizeof(struct user_fpxregs_struct)); + DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct)); DEFINE(HOST_IP, EIP); DEFINE(HOST_SP, UESP); diff --git a/arch/um/sys-x86_64/user-offsets.c b/arch/um/sys-x86_64/user-offsets.c index 2f3443c..9735854 100644 --- a/arch/um/sys-x86_64/user-offsets.c +++ b/arch/um/sys-x86_64/user-offsets.c @@ -24,7 +24,6 @@ void foo(void) OFFSET(HOST_SC_TRAPNO, sigcontext, trapno); DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); - DEFINE(HOST_XFP_SIZE, 0); DEFINE_LONGS(HOST_RBX, RBX); DEFINE_LONGS(HOST_RCX, RCX); DEFINE_LONGS(HOST_RDI, RDI); -- cgit v1.1 From 484f1e2c1ea58c6a4352313f7ee4edd4b52deecd Mon Sep 17 00:00:00 2001 From: Johann Felix Soden Date: Mon, 12 May 2008 14:01:51 -0700 Subject: uml: fix errno return Error returns are negative. Signed-off-by: Johann Felix Soden Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/hostaudio_kern.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c index ff1b22b..368219c 100644 --- a/arch/um/drivers/hostaudio_kern.c +++ b/arch/um/drivers/hostaudio_kern.c @@ -154,7 +154,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file, case SNDCTL_DSP_SUBDIVIDE: case SNDCTL_DSP_SETFRAGMENT: if (get_user(data, (int __user *) arg)) - return EFAULT; + return -EFAULT; break; default: break; -- cgit v1.1 From 43f5b3085fdd27c4edf535d938b2cb0ccead4f75 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:52 -0700 Subject: uml: fix build when SLOB is enabled Reintroduce uml_kmalloc for the benefit of UML libc code. The previous tactic of declaring __kmalloc so it could be called directly from the libc side of the house turned out to be getting too intimate with slab, and it doesn't work with slob. So, the uml_kmalloc wrapper is back. It calls kmalloc or whatever that translates into, and libc code calls it. kfree is left alone since that still works, leaving a somewhat inconsistent API. Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/chan_user.c | 1 + arch/um/drivers/cow_sys.h | 2 +- arch/um/drivers/daemon_user.c | 4 ++-- arch/um/drivers/fd.c | 2 +- arch/um/drivers/mcast_user.c | 3 ++- arch/um/drivers/net_user.c | 2 +- arch/um/drivers/port_user.c | 2 +- arch/um/drivers/pty.c | 2 +- arch/um/drivers/slip_user.c | 2 +- arch/um/drivers/tty.c | 2 +- arch/um/drivers/xterm.c | 2 +- arch/um/include/um_malloc.h | 9 +++------ arch/um/kernel/mem.c | 5 +++++ arch/um/os-Linux/drivers/ethertap_user.c | 4 ++-- arch/um/os-Linux/helper.c | 4 ++-- arch/um/os-Linux/main.c | 2 +- arch/um/os-Linux/sigio.c | 4 ++-- 17 files changed, 28 insertions(+), 24 deletions(-) diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index 0257640..cfeb3f4 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c @@ -11,6 +11,7 @@ #include #include #include "chan_user.h" +#include "kern_constants.h" #include "os.h" #include "um_malloc.h" #include "user.h" diff --git a/arch/um/drivers/cow_sys.h b/arch/um/drivers/cow_sys.h index ca8c9e1..f5701fd 100644 --- a/arch/um/drivers/cow_sys.h +++ b/arch/um/drivers/cow_sys.h @@ -8,7 +8,7 @@ static inline void *cow_malloc(int size) { - return kmalloc(size, UM_GFP_KERNEL); + return uml_kmalloc(size, UM_GFP_KERNEL); } static inline void cow_free(void *ptr) diff --git a/arch/um/drivers/daemon_user.c b/arch/um/drivers/daemon_user.c index f23c109..f8e85e0 100644 --- a/arch/um/drivers/daemon_user.c +++ b/arch/um/drivers/daemon_user.c @@ -34,7 +34,7 @@ static struct sockaddr_un *new_addr(void *name, int len) { struct sockaddr_un *sun; - sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); + sun = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); if (sun == NULL) { printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un " "failed\n"); @@ -83,7 +83,7 @@ static int connect_to_switch(struct daemon_data *pri) goto out_close; } - sun = kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); + sun = uml_kmalloc(sizeof(struct sockaddr_un), UM_GFP_KERNEL); if (sun == NULL) { printk(UM_KERN_ERR "new_addr: allocation of sockaddr_un " "failed\n"); diff --git a/arch/um/drivers/fd.c b/arch/um/drivers/fd.c index 0a2bb5b..f5a981a 100644 --- a/arch/um/drivers/fd.c +++ b/arch/um/drivers/fd.c @@ -40,7 +40,7 @@ static void *fd_init(char *str, int device, const struct chan_opts *opts) return NULL; } - data = kmalloc(sizeof(*data), UM_GFP_KERNEL); + data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL); if (data == NULL) return NULL; diff --git a/arch/um/drivers/mcast_user.c b/arch/um/drivers/mcast_user.c index 5f647d7..ee19e91 100644 --- a/arch/um/drivers/mcast_user.c +++ b/arch/um/drivers/mcast_user.c @@ -15,6 +15,7 @@ #include #include #include +#include "kern_constants.h" #include "mcast.h" #include "net_user.h" #include "um_malloc.h" @@ -24,7 +25,7 @@ static struct sockaddr_in *new_addr(char *addr, unsigned short port) { struct sockaddr_in *sin; - sin = kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); + sin = uml_kmalloc(sizeof(struct sockaddr_in), UM_GFP_KERNEL); if (sin == NULL) { printk(UM_KERN_ERR "new_addr: allocation of sockaddr_in " "failed\n"); diff --git a/arch/um/drivers/net_user.c b/arch/um/drivers/net_user.c index abf2653..9415dd9 100644 --- a/arch/um/drivers/net_user.c +++ b/arch/um/drivers/net_user.c @@ -222,7 +222,7 @@ static void change(char *dev, char *what, unsigned char *addr, netmask[2], netmask[3]); output_len = UM_KERN_PAGE_SIZE; - output = kmalloc(output_len, UM_GFP_KERNEL); + output = uml_kmalloc(output_len, UM_GFP_KERNEL); if (output == NULL) printk(UM_KERN_ERR "change : failed to allocate output " "buffer\n"); diff --git a/arch/um/drivers/port_user.c b/arch/um/drivers/port_user.c index d269ca3..b49bf56 100644 --- a/arch/um/drivers/port_user.c +++ b/arch/um/drivers/port_user.c @@ -47,7 +47,7 @@ static void *port_init(char *str, int device, const struct chan_opts *opts) if (kern_data == NULL) return NULL; - data = kmalloc(sizeof(*data), UM_GFP_KERNEL); + data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL); if (data == NULL) goto err; diff --git a/arch/um/drivers/pty.c b/arch/um/drivers/pty.c index 49c79dd..1113911 100644 --- a/arch/um/drivers/pty.c +++ b/arch/um/drivers/pty.c @@ -29,7 +29,7 @@ static void *pty_chan_init(char *str, int device, const struct chan_opts *opts) { struct pty_chan *data; - data = kmalloc(sizeof(*data), UM_GFP_KERNEL); + data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL); if (data == NULL) return NULL; diff --git a/arch/um/drivers/slip_user.c b/arch/um/drivers/slip_user.c index 8b80505..a1c2d2c 100644 --- a/arch/um/drivers/slip_user.c +++ b/arch/um/drivers/slip_user.c @@ -96,7 +96,7 @@ static int slip_tramp(char **argv, int fd) pid = err; output_len = UM_KERN_PAGE_SIZE; - output = kmalloc(output_len, UM_GFP_KERNEL); + output = uml_kmalloc(output_len, UM_GFP_KERNEL); if (output == NULL) { printk(UM_KERN_ERR "slip_tramp : failed to allocate output " "buffer\n"); diff --git a/arch/um/drivers/tty.c b/arch/um/drivers/tty.c index c930fed..495858a 100644 --- a/arch/um/drivers/tty.c +++ b/arch/um/drivers/tty.c @@ -29,7 +29,7 @@ static void *tty_chan_init(char *str, int device, const struct chan_opts *opts) } str++; - data = kmalloc(sizeof(*data), UM_GFP_KERNEL); + data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL); if (data == NULL) return NULL; *data = ((struct tty_chan) { .dev = str, diff --git a/arch/um/drivers/xterm.c b/arch/um/drivers/xterm.c index 8a1c18a..da2caa5 100644 --- a/arch/um/drivers/xterm.c +++ b/arch/um/drivers/xterm.c @@ -30,7 +30,7 @@ static void *xterm_init(char *str, int device, const struct chan_opts *opts) { struct xterm_chan *data; - data = kmalloc(sizeof(*data), UM_GFP_KERNEL); + data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL); if (data == NULL) return NULL; *data = ((struct xterm_chan) { .pid = -1, diff --git a/arch/um/include/um_malloc.h b/arch/um/include/um_malloc.h index 0ad17cb..c554d70 100644 --- a/arch/um/include/um_malloc.h +++ b/arch/um/include/um_malloc.h @@ -8,15 +8,12 @@ #include "kern_constants.h" -extern void *__kmalloc(int size, int flags); -static inline void *kmalloc(int size, int flags) -{ - return __kmalloc(size, flags); -} - +extern void *uml_kmalloc(int size, int flags); extern void kfree(const void *ptr); extern void *vmalloc(unsigned long size); extern void vfree(void *ptr); #endif /* __UM_MALLOC_H__ */ + + diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 2eea1ff..b0ee646 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -375,3 +375,8 @@ pmd_t *pmd_alloc_one(struct mm_struct *mm, unsigned long address) return pmd; } #endif + +void *uml_kmalloc(int size, int flags) +{ + return kmalloc(size, flags); +} diff --git a/arch/um/os-Linux/drivers/ethertap_user.c b/arch/um/os-Linux/drivers/ethertap_user.c index 6fb0b17..cc72cb2 100644 --- a/arch/um/os-Linux/drivers/ethertap_user.c +++ b/arch/um/os-Linux/drivers/ethertap_user.c @@ -52,7 +52,7 @@ static void etap_change(int op, unsigned char *addr, unsigned char *netmask, return; } - output = kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL); + output = uml_kmalloc(UM_KERN_PAGE_SIZE, UM_GFP_KERNEL); if (output == NULL) printk(UM_KERN_ERR "etap_change : Failed to allocate output " "buffer\n"); @@ -165,7 +165,7 @@ static int etap_open(void *data) err = etap_tramp(pri->dev_name, pri->gate_addr, control_fds[0], control_fds[1], data_fds[0], data_fds[1]); output_len = UM_KERN_PAGE_SIZE; - output = kmalloc(output_len, UM_GFP_KERNEL); + output = uml_kmalloc(output_len, UM_GFP_KERNEL); read_output(control_fds[0], output, output_len); if (output == NULL) diff --git a/arch/um/os-Linux/helper.c b/arch/um/os-Linux/helper.c index f25c29a..74ca7aa 100644 --- a/arch/um/os-Linux/helper.c +++ b/arch/um/os-Linux/helper.c @@ -71,8 +71,8 @@ int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv) data.pre_data = pre_data; data.argv = argv; data.fd = fds[1]; - data.buf = __cant_sleep() ? kmalloc(PATH_MAX, UM_GFP_ATOMIC) : - kmalloc(PATH_MAX, UM_GFP_KERNEL); + data.buf = __cant_sleep() ? uml_kmalloc(PATH_MAX, UM_GFP_ATOMIC) : + uml_kmalloc(PATH_MAX, UM_GFP_KERNEL); pid = clone(helper_child, (void *) sp, CLONE_VM, &data); if (pid < 0) { ret = -errno; diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c index abb9b0f..eee69b9 100644 --- a/arch/um/os-Linux/main.c +++ b/arch/um/os-Linux/main.c @@ -199,7 +199,7 @@ void *__wrap_malloc(int size) return __real_malloc(size); else if (size <= UM_KERN_PAGE_SIZE) /* finding contiguous pages can be hard*/ - ret = kmalloc(size, UM_GFP_KERNEL); + ret = uml_kmalloc(size, UM_GFP_KERNEL); else ret = vmalloc(size); /* diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c index abf47a7c..0578481 100644 --- a/arch/um/os-Linux/sigio.c +++ b/arch/um/os-Linux/sigio.c @@ -109,7 +109,7 @@ static int need_poll(struct pollfds *polls, int n) if (n <= polls->size) return 0; - new = kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC); + new = uml_kmalloc(n * sizeof(struct pollfd), UM_GFP_ATOMIC); if (new == NULL) { printk(UM_KERN_ERR "need_poll : failed to allocate new " "pollfds\n"); @@ -243,7 +243,7 @@ static struct pollfd *setup_initial_poll(int fd) { struct pollfd *p; - p = kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL); + p = uml_kmalloc(sizeof(struct pollfd), UM_GFP_KERNEL); if (p == NULL) { printk(UM_KERN_ERR "setup_initial_poll : failed to allocate " "poll\n"); -- cgit v1.1 From 309e96cdf2f2c1a071102e8bdf828a3493e6e50a Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:52 -0700 Subject: uml: remove unused header From: Adrian Bunk This patch removes the unused and broken (the normal asm/keyboard.h files no longer exists) include/asm-um/keyboard.h Signed-off-by: Adrian Bunk Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-um/keyboard.h | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 include/asm-um/keyboard.h diff --git a/include/asm-um/keyboard.h b/include/asm-um/keyboard.h deleted file mode 100644 index ee2e230..0000000 --- a/include/asm-um/keyboard.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef __UM_KEYBOARD_H -#define __UM_KEYBOARD_H - -#include "asm/arch/keyboard.h" - -#endif -- cgit v1.1 From cfd28f6695d0fc047478480791a21bdd4967f98e Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:53 -0700 Subject: uml: fix bad NTP interaction with clock UML's supposed nanosecond clock interacts badly with NTP when NTP decides that the clock has drifted ahead and needs to be slowed down. Slowing down the clock is done by decrementing the cycle-to-nanosecond multiplier, which is 1. Decrementing that gives you 0 and time is stopped. This is fixed by switching to a microsecond clock, with a multiplier of 1000. Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/time.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c index 0d0cea2..c3e2f36 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -75,7 +75,7 @@ static irqreturn_t um_timer(int irq, void *dev) static cycle_t itimer_read(void) { - return os_nsecs(); + return os_nsecs() / 1000; } static struct clocksource itimer_clocksource = { @@ -83,7 +83,7 @@ static struct clocksource itimer_clocksource = { .rating = 300, .read = itimer_read, .mask = CLOCKSOURCE_MASK(64), - .mult = 1, + .mult = 1000, .shift = 0, .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -- cgit v1.1 From 5563d722bfc73f27423fcb76240bfc1fb4284635 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:54 -0700 Subject: uml: use __SPIN_LOCK_UNLOCKED From: Robert P. J. Day Use newer, non-deprecated __SPIN_LOCK_UNLOCKED macro. Signed-off-by: Robert P. J. Day Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/line.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/um/include/line.h b/arch/um/include/line.h index 979b73e..311a0d3 100644 --- a/arch/um/include/line.h +++ b/arch/um/include/line.h @@ -58,11 +58,11 @@ struct line { }; #define LINE_INIT(str, d) \ - { .count_lock = SPIN_LOCK_UNLOCKED, \ + { .count_lock = __SPIN_LOCK_UNLOCKED((str).count_lock), \ .init_str = str, \ .init_pri = INIT_STATIC, \ .valid = 1, \ - .lock = SPIN_LOCK_UNLOCKED, \ + .lock = __SPIN_LOCK_UNLOCKED((str).lock), \ .driver = d } extern void line_close(struct tty_struct *tty, struct file * filp); -- cgit v1.1 From 63b9871f6ee2607f3b44e0044e145574b3f08619 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Mon, 12 May 2008 14:01:55 -0700 Subject: uml: fix CONFIG_RAW dependencies Add the BLOCK dependency for RAW_DRIVER, to match what's in drivers/char/Kconfig. Also, while we're there, update the alleged obsolesence of RAW_DRIVER since it doesn't seem to be going away any time soon. Signed-off-by: Robert P. J. Day Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/Kconfig.char | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/um/Kconfig.char b/arch/um/Kconfig.char index 3a4b396..1b238eb 100644 --- a/arch/um/Kconfig.char +++ b/arch/um/Kconfig.char @@ -145,14 +145,14 @@ config LEGACY_PTYS systems, it is safe to say N. config RAW_DRIVER - tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)" + tristate "RAW driver (/dev/raw/rawN)" + depends on BLOCK help The raw driver permits block devices to be bound to /dev/raw/rawN. Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. See the raw(8) manpage for more details. - The raw driver is deprecated and will be removed soon. - Applications should simply open the device (eg /dev/hda1) + Applications should preferably open the device (eg /dev/hda1) with the O_DIRECT flag. config MAX_RAW_DEVS -- cgit v1.1 From 6d0742426c9adc7465ef5c62a99a1d3e9696ea19 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Mon, 12 May 2008 14:01:56 -0700 Subject: uml: use DIV_ROUND_UP I just saw similar patches in the janitor kernel's list, and spotted place it fits. Signed-off-by: Jiri Olsa Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/ubd_kern.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 5e45e39..44ad160 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -1178,8 +1178,8 @@ static void cowify_bitmap(__u64 io_offset, int length, unsigned long *cow_mask, * by one word. Thanks to Lynn Kerby for the fix and James McMechan * for the original diagnosis. */ - if(*cow_offset == ((bitmap_len + sizeof(unsigned long) - 1) / - sizeof(unsigned long) - 1)) + if (*cow_offset == (DIV_ROUND_UP(bitmap_len, + sizeof(unsigned long)) - 1)) (*cow_offset)--; bitmap_words[0] = bitmap[*cow_offset]; -- cgit v1.1 From a7dfa9403bf3b03899d5ef5d10b0c5c3f74b0682 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 12 May 2008 14:01:56 -0700 Subject: uml: use PAGE_SIZE in linker scripts This patch includes page.h header into linker scripts that allow us to use PAGE_SIZE macro instead of numeric constant. To be able to include page.h into linker scripts page.h is needed for some modification - i.e. we need to use __ASSEMBLY__ and _AC macro [jdike@linux.intel.com - fixed conflict with as-layout.h] Signed-off-by: Cyrill Gorcunov Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/as-layout.h | 14 +++++++------- arch/um/kernel/dyn.lds.S | 7 ++++--- arch/um/kernel/uml.lds.S | 7 ++++--- include/asm-um/page.h | 17 +++++++++++------ 4 files changed, 26 insertions(+), 19 deletions(-) diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h index cac542d..58e852d 100644 --- a/arch/um/include/as-layout.h +++ b/arch/um/include/as-layout.h @@ -23,16 +23,16 @@ */ #ifdef __ASSEMBLY__ -#define _AC(X, Y) (Y) +#define _UML_AC(X, Y) (Y) #else -#define __AC(X, Y) (X (Y)) -#define _AC(X, Y) __AC(X, Y) +#define __UML_AC(X, Y) (X(Y)) +#define _UML_AC(X, Y) __UML_AC(X, Y) #endif -#define STUB_START _AC(, 0x100000) -#define STUB_CODE _AC((unsigned long), STUB_START) -#define STUB_DATA _AC((unsigned long), STUB_CODE + UM_KERN_PAGE_SIZE) -#define STUB_END _AC((unsigned long), STUB_DATA + UM_KERN_PAGE_SIZE) +#define STUB_START _UML_AC(, 0x100000) +#define STUB_CODE _UML_AC((unsigned long), STUB_START) +#define STUB_DATA _UML_AC((unsigned long), STUB_CODE + UM_KERN_PAGE_SIZE) +#define STUB_END _UML_AC((unsigned long), STUB_DATA + UM_KERN_PAGE_SIZE) #ifndef __ASSEMBLY__ diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index 26090b7..9975e1a 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S @@ -1,4 +1,5 @@ #include +#include OUTPUT_FORMAT(ELF_FORMAT) OUTPUT_ARCH(ELF_ARCH) @@ -21,7 +22,7 @@ SECTIONS _einittext = .; } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); /* Read-only sections, merged into text segment: */ .hash : { *(.hash) } @@ -68,9 +69,9 @@ SECTIONS /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); } =0x90909090 - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .syscall_stub : { __syscall_stub_start = .; *(.__syscall_stub*) diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index 5828c1d..11b8352 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S @@ -1,4 +1,5 @@ #include +#include OUTPUT_FORMAT(ELF_FORMAT) OUTPUT_ARCH(ELF_ARCH) @@ -26,7 +27,7 @@ SECTIONS INIT_TEXT _einittext = .; } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .text : { @@ -39,7 +40,7 @@ SECTIONS *(.gnu.linkonce.t*) } - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); .syscall_stub : { __syscall_stub_start = .; *(.__syscall_stub*) @@ -79,7 +80,7 @@ SECTIONS .sdata : { *(.sdata) } _edata = .; PROVIDE (edata = .); - . = ALIGN(0x1000); + . = ALIGN(PAGE_SIZE); .sbss : { __bss_start = .; diff --git a/include/asm-um/page.h b/include/asm-um/page.h index 381f96b..916e1a6 100644 --- a/include/asm-um/page.h +++ b/include/asm-um/page.h @@ -7,16 +7,20 @@ #ifndef __UM_PAGE_H #define __UM_PAGE_H -struct page; - -#include -#include +#include /* PAGE_SHIFT determines the page size */ #define PAGE_SHIFT 12 -#define PAGE_SIZE (1UL << PAGE_SHIFT) +#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) +#ifndef __ASSEMBLY__ + +struct page; + +#include +#include + /* * These are used to make use of C type-checking.. */ @@ -120,4 +124,5 @@ extern struct page *arch_validate(struct page *page, gfp_t mask, int order); #include #include -#endif +#endif /* __ASSEMBLY__ */ +#endif /* __UM_PAGE_H */ -- cgit v1.1 From 60a2988aea701a6424809a5432bf068667aac177 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:57 -0700 Subject: uml: physical memory shouldn't include initial stack The top of physical memory should be below the initial process stack, not the top of the address space, at least for as long as the stack isn't known to the kernel VM system and appropriately reserved. Cc: "Christopher S. Aker" Signed-off-by: Jeff Dike Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/kernel/um_arch.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 82058ac..9db85b2 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -258,6 +258,7 @@ int __init linux_main(int argc, char **argv) { unsigned long avail, diff; unsigned long virtmem_size, max_physmem; + unsigned long stack; unsigned int i; int add; char * mode; @@ -348,7 +349,9 @@ int __init linux_main(int argc, char **argv) } virtmem_size = physmem_size; - avail = TASK_SIZE - start_vm; + stack = (unsigned long) argv; + stack &= ~(1024 * 1024 - 1); + avail = stack - start_vm; if (physmem_size > avail) virtmem_size = avail; end_vm = start_vm + virtmem_size; -- cgit v1.1 From 5d33e4d7fd9a52d2673e5c730eab81856e100a74 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:58 -0700 Subject: uml: random driver fixes The random driver would essentially hang if the host's /dev/random returned -EAGAIN. There was a test of need_resched followed by a schedule inside the loop, but that didn't help and it's the wrong way to work anyway. The right way is to ask for an interrupt when there is input available from the host and handle it then rather than polling. Now, when the host's /dev/random returns -EAGAIN, the driver asks for a wakeup when there's randomness available again and sleeps. The interrupt routine just wakes up whatever processes are sleeping on host_read_wait. There is an atomic_t, host_sleep_count, which counts the number of processes waiting for randomness. When this reaches zero, the interrupt is disabled. An added complication is that async I/O notification was only recently added to /dev/random (by me), so essentially all hosts will lack it. So, we use the sigio workaround here, which is to have a separate thread poll on the descriptor and send an interrupt when there is input on it. This mechanism is activated when a process gets -EAGAIN (activating this multiple times is harmless, if a bit wasteful) and deactivated by the last process still waiting. The module name was changed from "random" to "hw_random" in order for udev to recognize it. The sigio workaround needed some changes. sigio_broken was added for cases when we know that async notification doesn't work. This is now called from maybe_sigio_broken, which deals with pts devices. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/random.c | 41 +++++++++++++++++++++++++++++++++++++---- arch/um/include/os.h | 1 + arch/um/include/process.h | 16 ++++------------ arch/um/os-Linux/sigio.c | 35 +++++++++++++++++++++-------------- include/asm-um/irq.h | 3 ++- 5 files changed, 65 insertions(+), 31 deletions(-) diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index 71f0959..f92b7c8 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c @@ -8,16 +8,18 @@ #include #include #include +#include #include #include #include +#include "irq_kern.h" #include "os.h" /* * core module and version information */ #define RNG_VERSION "1.0.0" -#define RNG_MODULE_NAME "random" +#define RNG_MODULE_NAME "hw_random" #define RNG_MISCDEV_MINOR 183 /* official */ @@ -26,6 +28,7 @@ * protects against a module being loaded twice at the same time. */ static int random_fd = -1; +static DECLARE_WAIT_QUEUE_HEAD(host_read_wait); static int rng_dev_open (struct inode *inode, struct file *filp) { @@ -38,6 +41,8 @@ static int rng_dev_open (struct inode *inode, struct file *filp) return 0; } +static atomic_t host_sleep_count = ATOMIC_INIT(0); + static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, loff_t * offp) { @@ -60,11 +65,26 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, } } else if(n == -EAGAIN){ + DECLARE_WAITQUEUE(wait, current); + if (filp->f_flags & O_NONBLOCK) return ret ? : -EAGAIN; - if(need_resched()) - schedule_timeout_interruptible(1); + atomic_inc(&host_sleep_count); + reactivate_fd(random_fd, RANDOM_IRQ); + add_sigio_fd(random_fd); + + add_wait_queue(&host_read_wait, &wait); + set_task_state(current, TASK_INTERRUPTIBLE); + + schedule(); + set_task_state(current, TASK_RUNNING); + remove_wait_queue(&host_read_wait, &wait); + + if (atomic_dec_and_test(&host_sleep_count)) { + ignore_sigio_fd(random_fd); + deactivate_fd(random_fd, RANDOM_IRQ); + } } else return n; if (signal_pending (current)) @@ -86,6 +106,13 @@ static struct miscdevice rng_miscdev = { &rng_chrdev_ops, }; +static irqreturn_t random_interrupt(int irq, void *data) +{ + wake_up(&host_read_wait); + + return IRQ_HANDLED; +} + /* * rng_init - initialize RNG module */ @@ -99,10 +126,14 @@ static int __init rng_init (void) random_fd = err; - err = os_set_fd_block(random_fd, 0); + err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt, + IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random", + NULL); if(err) goto err_out_cleanup_hw; + sigio_broken(random_fd, 1); + err = misc_register (&rng_miscdev); if (err) { printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n"); @@ -113,6 +144,7 @@ static int __init rng_init (void) return err; err_out_cleanup_hw: + os_close_file(random_fd); random_fd = -1; goto out; } @@ -122,6 +154,7 @@ static int __init rng_init (void) */ static void __exit rng_cleanup (void) { + os_close_file(random_fd); misc_deregister (&rng_miscdev); } diff --git a/arch/um/include/os.h b/arch/um/include/os.h index 32c799e..e2716ac 100644 --- a/arch/um/include/os.h +++ b/arch/um/include/os.h @@ -290,6 +290,7 @@ extern void os_set_ioignore(void); extern int add_sigio_fd(int fd); extern int ignore_sigio_fd(int fd); extern void maybe_sigio_broken(int fd, int read); +extern void sigio_broken(int fd, int read); /* sys-x86_64/prctl.c */ extern int os_arch_prctl(int pid, int code, unsigned long *addr); diff --git a/arch/um/include/process.h b/arch/um/include/process.h index 5af9157..838b480 100644 --- a/arch/um/include/process.h +++ b/arch/um/include/process.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -8,18 +8,10 @@ #include +/* Copied from linux/compiler-gcc.h since we can't include it directly */ +#define barrier() __asm__ __volatile__("": : :"memory") + extern void sig_handler(int sig, struct sigcontext sc); extern void alarm_handler(int sig, struct sigcontext sc); #endif - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c index 0578481..eb8f2e4 100644 --- a/arch/um/os-Linux/sigio.c +++ b/arch/um/os-Linux/sigio.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) + * Copyright (C) 2002 - 2008 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ @@ -15,6 +15,7 @@ #include "kern_util.h" #include "init.h" #include "os.h" +#include "process.h" #include "sigio.h" #include "um_malloc.h" #include "user.h" @@ -338,20 +339,10 @@ out_close1: close(l_write_sigio_fds[1]); } -/* Changed during early boot */ -static int pty_output_sigio = 0; -static int pty_close_sigio = 0; - -void maybe_sigio_broken(int fd, int read) +void sigio_broken(int fd, int read) { int err; - if (!isatty(fd)) - return; - - if ((read || pty_output_sigio) && (!read || pty_close_sigio)) - return; - write_sigio_workaround(); sigio_lock(); @@ -370,6 +361,21 @@ out: sigio_unlock(); } +/* Changed during early boot */ +static int pty_output_sigio; +static int pty_close_sigio; + +void maybe_sigio_broken(int fd, int read) +{ + if (!isatty(fd)) + return; + + if ((read || pty_output_sigio) && (!read || pty_close_sigio)) + return; + + sigio_broken(fd, read); +} + static void sigio_cleanup(void) { if (write_sigio_pid == -1) @@ -383,7 +389,7 @@ static void sigio_cleanup(void) __uml_exitcall(sigio_cleanup); /* Used as a flag during SIGIO testing early in boot */ -static volatile int got_sigio = 0; +static int got_sigio; static void __init handler(int sig) { @@ -498,7 +504,8 @@ static void tty_output(int master, int slave) if (errno != EAGAIN) printk(UM_KERN_ERR "tty_output : write failed, errno = %d\n", errno); - while (((n = read(slave, buf, sizeof(buf))) > 0) && !got_sigio) + while (((n = read(slave, buf, sizeof(buf))) > 0) && + !({ barrier(); got_sigio; })) ; if (got_sigio) { diff --git a/include/asm-um/irq.h b/include/asm-um/irq.h index de389a4..4a2037f 100644 --- a/include/asm-um/irq.h +++ b/include/asm-um/irq.h @@ -15,8 +15,9 @@ #define SIGIO_WRITE_IRQ 11 #define TELNETD_IRQ 12 #define XTERM_IRQ 13 +#define RANDOM_IRQ 14 -#define LAST_IRQ XTERM_IRQ +#define LAST_IRQ RANDOM_IRQ #define NR_IRQS (LAST_IRQ + 1) #endif -- cgit v1.1 From 3d88958e01e71bb14a367db75f12f7a59c068f02 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:01:59 -0700 Subject: uml: style fixes in the random driver Give random.c a style workover while I'm changing it. Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/drivers/random.c | 79 +++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/arch/um/drivers/random.c b/arch/um/drivers/random.c index f92b7c8..4949044 100644 --- a/arch/um/drivers/random.c +++ b/arch/um/drivers/random.c @@ -1,4 +1,5 @@ -/* Copyright (C) 2005 Jeff Dike */ +/* Copyright (C) 2005 - 2008 Jeff Dike */ + /* Much of this ripped from drivers/char/hw_random.c, see there for other * copyright. * @@ -35,7 +36,7 @@ static int rng_dev_open (struct inode *inode, struct file *filp) /* enforce read-only access to this chrdev */ if ((filp->f_mode & FMODE_READ) == 0) return -EINVAL; - if (filp->f_mode & FMODE_WRITE) + if ((filp->f_mode & FMODE_WRITE) != 0) return -EINVAL; return 0; @@ -44,31 +45,31 @@ static int rng_dev_open (struct inode *inode, struct file *filp) static atomic_t host_sleep_count = ATOMIC_INIT(0); static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, - loff_t * offp) + loff_t *offp) { - u32 data; - int n, ret = 0, have_data; - - while(size){ - n = os_read_file(random_fd, &data, sizeof(data)); - if(n > 0){ - have_data = n; - while (have_data && size) { - if (put_user((u8)data, buf++)) { - ret = ret ? : -EFAULT; - break; - } - size--; - ret++; - have_data--; - data>>=8; - } - } - else if(n == -EAGAIN){ + u32 data; + int n, ret = 0, have_data; + + while (size) { + n = os_read_file(random_fd, &data, sizeof(data)); + if (n > 0) { + have_data = n; + while (have_data && size) { + if (put_user((u8) data, buf++)) { + ret = ret ? : -EFAULT; + break; + } + size--; + ret++; + have_data--; + data >>= 8; + } + } + else if (n == -EAGAIN) { DECLARE_WAITQUEUE(wait, current); - if (filp->f_flags & O_NONBLOCK) - return ret ? : -EAGAIN; + if (filp->f_flags & O_NONBLOCK) + return ret ? : -EAGAIN; atomic_inc(&host_sleep_count); reactivate_fd(random_fd, RANDOM_IRQ); @@ -85,8 +86,10 @@ static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size, ignore_sigio_fd(random_fd); deactivate_fd(random_fd, RANDOM_IRQ); } - } - else return n; + } + else + return n; + if (signal_pending (current)) return ret ? : -ERESTARTSYS; } @@ -120,33 +123,33 @@ static int __init rng_init (void) { int err; - err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0); - if(err < 0) - goto out; + err = os_open_file("/dev/random", of_read(OPENFLAGS()), 0); + if (err < 0) + goto out; - random_fd = err; + random_fd = err; err = um_request_irq(RANDOM_IRQ, random_fd, IRQ_READ, random_interrupt, IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "random", NULL); - if(err) + if (err) goto err_out_cleanup_hw; sigio_broken(random_fd, 1); err = misc_register (&rng_miscdev); if (err) { - printk (KERN_ERR RNG_MODULE_NAME ": misc device register failed\n"); + printk (KERN_ERR RNG_MODULE_NAME ": misc device register " + "failed\n"); goto err_out_cleanup_hw; } +out: + return err; - out: - return err; - - err_out_cleanup_hw: +err_out_cleanup_hw: os_close_file(random_fd); - random_fd = -1; - goto out; + random_fd = -1; + goto out; } /* -- cgit v1.1 From fe2cc53ee013a4d4d0317d418e7019fe6533a5a8 Mon Sep 17 00:00:00 2001 From: Jeff Dike Date: Mon, 12 May 2008 14:02:00 -0700 Subject: uml: track and make up lost ticks Alarm delivery could be noticably late in the !CONFIG_NOHZ case because lost ticks weren't being taken into account. This is now treated more carefully, with the time between ticks being calculated and the appropriate number of ticks delivered to the timekeeping system. Cc: Nix Signed-off-by: Jeff Dike Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/um/include/process.h | 4 ++-- arch/um/os-Linux/signal.c | 1 + arch/um/os-Linux/time.c | 54 +++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/arch/um/include/process.h b/arch/um/include/process.h index 838b480..bb873a5 100644 --- a/arch/um/include/process.h +++ b/arch/um/include/process.h @@ -11,7 +11,7 @@ /* Copied from linux/compiler-gcc.h since we can't include it directly */ #define barrier() __asm__ __volatile__("": : :"memory") -extern void sig_handler(int sig, struct sigcontext sc); -extern void alarm_handler(int sig, struct sigcontext sc); +extern void sig_handler(int sig, struct sigcontext *sc); +extern void alarm_handler(int sig, struct sigcontext *sc); #endif diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 3f1694b..5aade60 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -12,6 +12,7 @@ #include "as-layout.h" #include "kern_util.h" #include "os.h" +#include "process.h" #include "sysdep/barrier.h" #include "sysdep/sigcontext.h" #include "user.h" diff --git a/arch/um/os-Linux/time.c b/arch/um/os-Linux/time.c index e492805..bee98f4 100644 --- a/arch/um/os-Linux/time.c +++ b/arch/um/os-Linux/time.c @@ -9,7 +9,9 @@ #include #include #include "kern_constants.h" +#include "kern_util.h" #include "os.h" +#include "process.h" #include "user.h" int set_interval(void) @@ -58,12 +60,17 @@ static inline long long timeval_to_ns(const struct timeval *tv) long long disable_timer(void) { struct itimerval time = ((struct itimerval) { { 0, 0 }, { 0, 0 } }); + int remain, max = UM_NSEC_PER_SEC / UM_HZ; if (setitimer(ITIMER_VIRTUAL, &time, &time) < 0) printk(UM_KERN_ERR "disable_timer - setitimer failed, " "errno = %d\n", errno); - return timeval_to_ns(&time.it_value); + remain = timeval_to_ns(&time.it_value); + if (remain > max) + remain = max; + + return remain; } long long os_nsecs(void) @@ -79,7 +86,44 @@ static int after_sleep_interval(struct timespec *ts) { return 0; } + +static void deliver_alarm(void) +{ + alarm_handler(SIGVTALRM, NULL); +} + +static unsigned long long sleep_time(unsigned long long nsecs) +{ + return nsecs; +} + #else +unsigned long long last_tick; +unsigned long long skew; + +static void deliver_alarm(void) +{ + unsigned long long this_tick = os_nsecs(); + int one_tick = UM_NSEC_PER_SEC / UM_HZ; + + if (last_tick == 0) + last_tick = this_tick - one_tick; + + skew += this_tick - last_tick; + + while (skew >= one_tick) { + alarm_handler(SIGVTALRM, NULL); + skew -= one_tick; + } + + last_tick = this_tick; +} + +static unsigned long long sleep_time(unsigned long long nsecs) +{ + return nsecs > skew ? nsecs - skew : 0; +} + static inline long long timespec_to_us(const struct timespec *ts) { return ((long long) ts->tv_sec * UM_USEC_PER_SEC) + @@ -102,6 +146,8 @@ static int after_sleep_interval(struct timespec *ts) */ if (start_usecs > usec) start_usecs = usec; + + start_usecs -= skew / UM_NSEC_PER_USEC; tv = ((struct timeval) { .tv_sec = start_usecs / UM_USEC_PER_SEC, .tv_usec = start_usecs % UM_USEC_PER_SEC }); interval = ((struct itimerval) { { 0, usec }, tv }); @@ -113,8 +159,6 @@ static int after_sleep_interval(struct timespec *ts) } #endif -extern void alarm_handler(int sig, struct sigcontext *sc); - void idle_sleep(unsigned long long nsecs) { struct timespec ts; @@ -126,10 +170,12 @@ void idle_sleep(unsigned long long nsecs) */ if (nsecs == 0) nsecs = UM_NSEC_PER_SEC / UM_HZ; + + nsecs = sleep_time(nsecs); ts = ((struct timespec) { .tv_sec = nsecs / UM_NSEC_PER_SEC, .tv_nsec = nsecs % UM_NSEC_PER_SEC }); if (nanosleep(&ts, &ts) == 0) - alarm_handler(SIGVTALRM, NULL); + deliver_alarm(); after_sleep_interval(&ts); } -- cgit v1.1 From 0cf942d75a6acfa11a41f63330d8780901eda4af Mon Sep 17 00:00:00 2001 From: Eric BENARD Date: Mon, 12 May 2008 14:02:01 -0700 Subject: spi: pxa2xx_spi clock resume bugfix There is a typo in pxa2xx_spi.c, comment says "Enable the SSP clock", code says: clk_disable ... so after resume, the SSP is dead. Signed-off-by: David Brownell Cc: Ned Forrester Cc: Stephen Street Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/pxa2xx_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 654bb58..0c452c4 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -1567,7 +1567,7 @@ static int pxa2xx_spi_resume(struct platform_device *pdev) int status = 0; /* Enable the SSP clock */ - clk_disable(ssp->clk); + clk_enable(ssp->clk); /* Start the queue running */ status = start_queue(drv_data); -- cgit v1.1 From 65c17b801e03e40acdca0cd34e8eb1b8a347b539 Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Mon, 12 May 2008 14:02:02 -0700 Subject: drivers/misc/sgi-xp: clean up return values Make XP return values more generic to XP and not so tied to XPC by changing enum xpc_retval to xp_retval, along with changing return value prefixes from xpc to xp. Also, cleanup a comment block that referenced some of these return values as well as the handling of BTE related return values. Signed-off-by: Dean Nelson Acked-by: Robin Holt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/sgi-xp/xp.h | 291 +++++++++++++----------------------- drivers/misc/sgi-xp/xp_main.c | 38 ++--- drivers/misc/sgi-xp/xpc.h | 71 +++------ drivers/misc/sgi-xp/xpc_channel.c | 166 ++++++++++---------- drivers/misc/sgi-xp/xpc_main.c | 44 +++--- drivers/misc/sgi-xp/xpc_partition.c | 64 ++++---- drivers/misc/sgi-xp/xpnet.c | 18 +-- 7 files changed, 291 insertions(+), 401 deletions(-) diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h index 5515234..a258fa6 100644 --- a/drivers/misc/sgi-xp/xp.h +++ b/drivers/misc/sgi-xp/xp.h @@ -157,215 +157,136 @@ struct xpc_msg { /* * Define the return values and values passed to user's callout functions. * (It is important to add new value codes at the end just preceding - * xpcUnknownReason, which must have the highest numerical value.) + * xpUnknownReason, which must have the highest numerical value.) */ -enum xpc_retval { - xpcSuccess = 0, +enum xp_retval { + xpSuccess = 0, - xpcNotConnected, /* 1: channel is not connected */ - xpcConnected, /* 2: channel connected (opened) */ - xpcRETIRED1, /* 3: (formerly xpcDisconnected) */ + xpNotConnected, /* 1: channel is not connected */ + xpConnected, /* 2: channel connected (opened) */ + xpRETIRED1, /* 3: (formerly xpDisconnected) */ - xpcMsgReceived, /* 4: message received */ - xpcMsgDelivered, /* 5: message delivered and acknowledged */ + xpMsgReceived, /* 4: message received */ + xpMsgDelivered, /* 5: message delivered and acknowledged */ - xpcRETIRED2, /* 6: (formerly xpcTransferFailed) */ + xpRETIRED2, /* 6: (formerly xpTransferFailed) */ - xpcNoWait, /* 7: operation would require wait */ - xpcRetry, /* 8: retry operation */ - xpcTimeout, /* 9: timeout in xpc_allocate_msg_wait() */ - xpcInterrupted, /* 10: interrupted wait */ + xpNoWait, /* 7: operation would require wait */ + xpRetry, /* 8: retry operation */ + xpTimeout, /* 9: timeout in xpc_allocate_msg_wait() */ + xpInterrupted, /* 10: interrupted wait */ - xpcUnequalMsgSizes, /* 11: message size disparity between sides */ - xpcInvalidAddress, /* 12: invalid address */ + xpUnequalMsgSizes, /* 11: message size disparity between sides */ + xpInvalidAddress, /* 12: invalid address */ - xpcNoMemory, /* 13: no memory available for XPC structures */ - xpcLackOfResources, /* 14: insufficient resources for operation */ - xpcUnregistered, /* 15: channel is not registered */ - xpcAlreadyRegistered, /* 16: channel is already registered */ + xpNoMemory, /* 13: no memory available for XPC structures */ + xpLackOfResources, /* 14: insufficient resources for operation */ + xpUnregistered, /* 15: channel is not registered */ + xpAlreadyRegistered, /* 16: channel is already registered */ - xpcPartitionDown, /* 17: remote partition is down */ - xpcNotLoaded, /* 18: XPC module is not loaded */ - xpcUnloading, /* 19: this side is unloading XPC module */ + xpPartitionDown, /* 17: remote partition is down */ + xpNotLoaded, /* 18: XPC module is not loaded */ + xpUnloading, /* 19: this side is unloading XPC module */ - xpcBadMagic, /* 20: XPC MAGIC string not found */ + xpBadMagic, /* 20: XPC MAGIC string not found */ - xpcReactivating, /* 21: remote partition was reactivated */ + xpReactivating, /* 21: remote partition was reactivated */ - xpcUnregistering, /* 22: this side is unregistering channel */ - xpcOtherUnregistering, /* 23: other side is unregistering channel */ + xpUnregistering, /* 22: this side is unregistering channel */ + xpOtherUnregistering, /* 23: other side is unregistering channel */ - xpcCloneKThread, /* 24: cloning kernel thread */ - xpcCloneKThreadFailed, /* 25: cloning kernel thread failed */ + xpCloneKThread, /* 24: cloning kernel thread */ + xpCloneKThreadFailed, /* 25: cloning kernel thread failed */ - xpcNoHeartbeat, /* 26: remote partition has no heartbeat */ + xpNoHeartbeat, /* 26: remote partition has no heartbeat */ - xpcPioReadError, /* 27: PIO read error */ - xpcPhysAddrRegFailed, /* 28: registration of phys addr range failed */ + xpPioReadError, /* 27: PIO read error */ + xpPhysAddrRegFailed, /* 28: registration of phys addr range failed */ - xpcBteDirectoryError, /* 29: maps to BTEFAIL_DIR */ - xpcBtePoisonError, /* 30: maps to BTEFAIL_POISON */ - xpcBteWriteError, /* 31: maps to BTEFAIL_WERR */ - xpcBteAccessError, /* 32: maps to BTEFAIL_ACCESS */ - xpcBtePWriteError, /* 33: maps to BTEFAIL_PWERR */ - xpcBtePReadError, /* 34: maps to BTEFAIL_PRERR */ - xpcBteTimeOutError, /* 35: maps to BTEFAIL_TOUT */ - xpcBteXtalkError, /* 36: maps to BTEFAIL_XTERR */ - xpcBteNotAvailable, /* 37: maps to BTEFAIL_NOTAVAIL */ - xpcBteUnmappedError, /* 38: unmapped BTEFAIL_ error */ + xpRETIRED3, /* 29: (formerly xpBteDirectoryError) */ + xpRETIRED4, /* 30: (formerly xpBtePoisonError) */ + xpRETIRED5, /* 31: (formerly xpBteWriteError) */ + xpRETIRED6, /* 32: (formerly xpBteAccessError) */ + xpRETIRED7, /* 33: (formerly xpBtePWriteError) */ + xpRETIRED8, /* 34: (formerly xpBtePReadError) */ + xpRETIRED9, /* 35: (formerly xpBteTimeOutError) */ + xpRETIRED10, /* 36: (formerly xpBteXtalkError) */ + xpRETIRED11, /* 37: (formerly xpBteNotAvailable) */ + xpRETIRED12, /* 38: (formerly xpBteUnmappedError) */ - xpcBadVersion, /* 39: bad version number */ - xpcVarsNotSet, /* 40: the XPC variables are not set up */ - xpcNoRsvdPageAddr, /* 41: unable to get rsvd page's phys addr */ - xpcInvalidPartid, /* 42: invalid partition ID */ - xpcLocalPartid, /* 43: local partition ID */ + xpBadVersion, /* 39: bad version number */ + xpVarsNotSet, /* 40: the XPC variables are not set up */ + xpNoRsvdPageAddr, /* 41: unable to get rsvd page's phys addr */ + xpInvalidPartid, /* 42: invalid partition ID */ + xpLocalPartid, /* 43: local partition ID */ - xpcOtherGoingDown, /* 44: other side going down, reason unknown */ - xpcSystemGoingDown, /* 45: system is going down, reason unknown */ - xpcSystemHalt, /* 46: system is being halted */ - xpcSystemReboot, /* 47: system is being rebooted */ - xpcSystemPoweroff, /* 48: system is being powered off */ + xpOtherGoingDown, /* 44: other side going down, reason unknown */ + xpSystemGoingDown, /* 45: system is going down, reason unknown */ + xpSystemHalt, /* 46: system is being halted */ + xpSystemReboot, /* 47: system is being rebooted */ + xpSystemPoweroff, /* 48: system is being powered off */ - xpcDisconnecting, /* 49: channel disconnecting (closing) */ + xpDisconnecting, /* 49: channel disconnecting (closing) */ - xpcOpenCloseError, /* 50: channel open/close protocol error */ + xpOpenCloseError, /* 50: channel open/close protocol error */ - xpcDisconnected, /* 51: channel disconnected (closed) */ + xpDisconnected, /* 51: channel disconnected (closed) */ - xpcBteSh2Start, /* 52: BTE CRB timeout */ + xpBteCopyError, /* 52: bte_copy() returned error */ - /* 53: 0x1 BTE Error Response Short */ - xpcBteSh2RspShort = xpcBteSh2Start + BTEFAIL_SH2_RESP_SHORT, - - /* 54: 0x2 BTE Error Response Long */ - xpcBteSh2RspLong = xpcBteSh2Start + BTEFAIL_SH2_RESP_LONG, - - /* 56: 0x4 BTE Error Response DSB */ - xpcBteSh2RspDSB = xpcBteSh2Start + BTEFAIL_SH2_RESP_DSP, - - /* 60: 0x8 BTE Error Response Access */ - xpcBteSh2RspAccess = xpcBteSh2Start + BTEFAIL_SH2_RESP_ACCESS, - - /* 68: 0x10 BTE Error CRB timeout */ - xpcBteSh2CRBTO = xpcBteSh2Start + BTEFAIL_SH2_CRB_TO, - - /* 84: 0x20 BTE Error NACK limit */ - xpcBteSh2NACKLimit = xpcBteSh2Start + BTEFAIL_SH2_NACK_LIMIT, - - /* 115: BTE end */ - xpcBteSh2End = xpcBteSh2Start + BTEFAIL_SH2_ALL, - - xpcUnknownReason /* 116: unknown reason - must be last in enum */ + xpUnknownReason /* 53: unknown reason - must be last in enum */ }; /* - * Define the callout function types used by XPC to update the user on - * connection activity and state changes (via the user function registered by - * xpc_connect()) and to notify them of messages received and delivered (via - * the user function registered by xpc_send_notify()). - * - * The two function types are xpc_channel_func and xpc_notify_func and - * both share the following arguments, with the exception of "data", which - * only xpc_channel_func has. + * Define the callout function type used by XPC to update the user on + * connection activity and state changes via the user function registered + * by xpc_connect(). * * Arguments: * - * reason - reason code. (See following table.) + * reason - reason code. * partid - partition ID associated with condition. * ch_number - channel # associated with condition. - * data - pointer to optional data. (See following table.) + * data - pointer to optional data. * key - pointer to optional user-defined value provided as the "key" - * argument to xpc_connect() or xpc_send_notify(). + * argument to xpc_connect(). * - * In the following table the "Optional Data" column applies to callouts made - * to functions registered by xpc_connect(). A "NA" in that column indicates - * that this reason code can be passed to functions registered by - * xpc_send_notify() (i.e. they don't have data arguments). + * A reason code of xpConnected indicates that a connection has been + * established to the specified partition on the specified channel. The data + * argument indicates the max number of entries allowed in the message queue. * - * Also, the first three reason codes in the following table indicate - * success, whereas the others indicate failure. When a failure reason code - * is received, one can assume that the channel is not connected. + * A reason code of xpMsgReceived indicates that a XPC message arrived from + * the specified partition on the specified channel. The data argument + * specifies the address of the message's payload. The user must call + * xpc_received() when finished with the payload. * - * - * Reason Code | Cause | Optional Data - * =====================+================================+===================== - * xpcConnected | connection has been established| max #of entries - * | to the specified partition on | allowed in message - * | the specified channel | queue - * ---------------------+--------------------------------+--------------------- - * xpcMsgReceived | an XPC message arrived from | address of payload - * | the specified partition on the | - * | specified channel | [the user must call - * | | xpc_received() when - * | | finished with the - * | | payload] - * ---------------------+--------------------------------+--------------------- - * xpcMsgDelivered | notification that the message | NA - * | was delivered to the intended | - * | recipient and that they have | - * | acknowledged its receipt by | - * | calling xpc_received() | - * =====================+================================+===================== - * xpcUnequalMsgSizes | can't connect to the specified | NULL - * | partition on the specified | - * | channel because of mismatched | - * | message sizes | - * ---------------------+--------------------------------+--------------------- - * xpcNoMemory | insufficient memory avaiable | NULL - * | to allocate message queue | - * ---------------------+--------------------------------+--------------------- - * xpcLackOfResources | lack of resources to create | NULL - * | the necessary kthreads to | - * | support the channel | - * ---------------------+--------------------------------+--------------------- - * xpcUnregistering | this side's user has | NULL or NA - * | unregistered by calling | - * | xpc_disconnect() | - * ---------------------+--------------------------------+--------------------- - * xpcOtherUnregistering| the other side's user has | NULL or NA - * | unregistered by calling | - * | xpc_disconnect() | - * ---------------------+--------------------------------+--------------------- - * xpcNoHeartbeat | the other side's XPC is no | NULL or NA - * | longer heartbeating | - * | | - * ---------------------+--------------------------------+--------------------- - * xpcUnloading | this side's XPC module is | NULL or NA - * | being unloaded | - * | | - * ---------------------+--------------------------------+--------------------- - * xpcOtherUnloading | the other side's XPC module is | NULL or NA - * | is being unloaded | - * | | - * ---------------------+--------------------------------+--------------------- - * xpcPioReadError | xp_nofault_PIOR() returned an | NULL or NA - * | error while sending an IPI | - * | | - * ---------------------+--------------------------------+--------------------- - * xpcInvalidAddress | the address either received or | NULL or NA - * | sent by the specified partition| - * | is invalid | - * ---------------------+--------------------------------+--------------------- - * xpcBteNotAvailable | attempt to pull data from the | NULL or NA - * xpcBtePoisonError | specified partition over the | - * xpcBteWriteError | specified channel via a | - * xpcBteAccessError | bte_copy() failed | - * xpcBteTimeOutError | | - * xpcBteXtalkError | | - * xpcBteDirectoryError | | - * xpcBteGenericError | | - * xpcBteUnmappedError | | - * ---------------------+--------------------------------+--------------------- - * xpcUnknownReason | the specified channel to the | NULL or NA - * | specified partition was | - * | unavailable for unknown reasons| - * =====================+================================+===================== + * All other reason codes indicate failure. The data argmument is NULL. + * When a failure reason code is received, one can assume that the channel + * is not connected. */ - -typedef void (*xpc_channel_func) (enum xpc_retval reason, partid_t partid, +typedef void (*xpc_channel_func) (enum xp_retval reason, partid_t partid, int ch_number, void *data, void *key); -typedef void (*xpc_notify_func) (enum xpc_retval reason, partid_t partid, +/* + * Define the callout function type used by XPC to notify the user of + * messages received and delivered via the user function registered by + * xpc_send_notify(). + * + * Arguments: + * + * reason - reason code. + * partid - partition ID associated with condition. + * ch_number - channel # associated with condition. + * key - pointer to optional user-defined value provided as the "key" + * argument to xpc_send_notify(). + * + * A reason code of xpMsgDelivered indicates that the message was delivered + * to the intended recipient and that they have acknowledged its receipt by + * calling xpc_received(). + * + * All other reason codes indicate failure. + */ +typedef void (*xpc_notify_func) (enum xp_retval reason, partid_t partid, int ch_number, void *key); /* @@ -401,43 +322,43 @@ struct xpc_registration { struct xpc_interface { void (*connect) (int); void (*disconnect) (int); - enum xpc_retval (*allocate) (partid_t, int, u32, void **); - enum xpc_retval (*send) (partid_t, int, void *); - enum xpc_retval (*send_notify) (partid_t, int, void *, + enum xp_retval (*allocate) (partid_t, int, u32, void **); + enum xp_retval (*send) (partid_t, int, void *); + enum xp_retval (*send_notify) (partid_t, int, void *, xpc_notify_func, void *); void (*received) (partid_t, int, void *); - enum xpc_retval (*partid_to_nasids) (partid_t, void *); + enum xp_retval (*partid_to_nasids) (partid_t, void *); }; extern struct xpc_interface xpc_interface; extern void xpc_set_interface(void (*)(int), void (*)(int), - enum xpc_retval (*)(partid_t, int, u32, void **), - enum xpc_retval (*)(partid_t, int, void *), - enum xpc_retval (*)(partid_t, int, void *, + enum xp_retval (*)(partid_t, int, u32, void **), + enum xp_retval (*)(partid_t, int, void *), + enum xp_retval (*)(partid_t, int, void *, xpc_notify_func, void *), void (*)(partid_t, int, void *), - enum xpc_retval (*)(partid_t, void *)); + enum xp_retval (*)(partid_t, void *)); extern void xpc_clear_interface(void); -extern enum xpc_retval xpc_connect(int, xpc_channel_func, void *, u16, +extern enum xp_retval xpc_connect(int, xpc_channel_func, void *, u16, u16, u32, u32); extern void xpc_disconnect(int); -static inline enum xpc_retval +static inline enum xp_retval xpc_allocate(partid_t partid, int ch_number, u32 flags, void **payload) { return xpc_interface.allocate(partid, ch_number, flags, payload); } -static inline enum xpc_retval +static inline enum xp_retval xpc_send(partid_t partid, int ch_number, void *payload) { return xpc_interface.send(partid, ch_number, payload); } -static inline enum xpc_retval +static inline enum xp_retval xpc_send_notify(partid_t partid, int ch_number, void *payload, xpc_notify_func func, void *key) { @@ -450,7 +371,7 @@ xpc_received(partid_t partid, int ch_number, void *payload) return xpc_interface.received(partid, ch_number, payload); } -static inline enum xpc_retval +static inline enum xp_retval xpc_partid_to_nasids(partid_t partid, void *nasids) { return xpc_interface.partid_to_nasids(partid, nasids); diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c index 1fbf99b..0eadaaa 100644 --- a/drivers/misc/sgi-xp/xp_main.c +++ b/drivers/misc/sgi-xp/xp_main.c @@ -42,21 +42,21 @@ EXPORT_SYMBOL_GPL(xpc_registrations); /* * Initialize the XPC interface to indicate that XPC isn't loaded. */ -static enum xpc_retval +static enum xp_retval xpc_notloaded(void) { - return xpcNotLoaded; + return xpNotLoaded; } struct xpc_interface xpc_interface = { (void (*)(int))xpc_notloaded, (void (*)(int))xpc_notloaded, - (enum xpc_retval(*)(partid_t, int, u32, void **))xpc_notloaded, - (enum xpc_retval(*)(partid_t, int, void *))xpc_notloaded, - (enum xpc_retval(*)(partid_t, int, void *, xpc_notify_func, void *)) + (enum xp_retval(*)(partid_t, int, u32, void **))xpc_notloaded, + (enum xp_retval(*)(partid_t, int, void *))xpc_notloaded, + (enum xp_retval(*)(partid_t, int, void *, xpc_notify_func, void *)) xpc_notloaded, (void (*)(partid_t, int, void *))xpc_notloaded, - (enum xpc_retval(*)(partid_t, void *))xpc_notloaded + (enum xp_retval(*)(partid_t, void *))xpc_notloaded }; EXPORT_SYMBOL_GPL(xpc_interface); @@ -66,12 +66,12 @@ EXPORT_SYMBOL_GPL(xpc_interface); void xpc_set_interface(void (*connect) (int), void (*disconnect) (int), - enum xpc_retval (*allocate) (partid_t, int, u32, void **), - enum xpc_retval (*send) (partid_t, int, void *), - enum xpc_retval (*send_notify) (partid_t, int, void *, + enum xp_retval (*allocate) (partid_t, int, u32, void **), + enum xp_retval (*send) (partid_t, int, void *), + enum xp_retval (*send_notify) (partid_t, int, void *, xpc_notify_func, void *), void (*received) (partid_t, int, void *), - enum xpc_retval (*partid_to_nasids) (partid_t, void *)) + enum xp_retval (*partid_to_nasids) (partid_t, void *)) { xpc_interface.connect = connect; xpc_interface.disconnect = disconnect; @@ -91,16 +91,16 @@ xpc_clear_interface(void) { xpc_interface.connect = (void (*)(int))xpc_notloaded; xpc_interface.disconnect = (void (*)(int))xpc_notloaded; - xpc_interface.allocate = (enum xpc_retval(*)(partid_t, int, u32, + xpc_interface.allocate = (enum xp_retval(*)(partid_t, int, u32, void **))xpc_notloaded; - xpc_interface.send = (enum xpc_retval(*)(partid_t, int, void *)) + xpc_interface.send = (enum xp_retval(*)(partid_t, int, void *)) xpc_notloaded; - xpc_interface.send_notify = (enum xpc_retval(*)(partid_t, int, void *, + xpc_interface.send_notify = (enum xp_retval(*)(partid_t, int, void *, xpc_notify_func, void *))xpc_notloaded; xpc_interface.received = (void (*)(partid_t, int, void *)) xpc_notloaded; - xpc_interface.partid_to_nasids = (enum xpc_retval(*)(partid_t, void *)) + xpc_interface.partid_to_nasids = (enum xp_retval(*)(partid_t, void *)) xpc_notloaded; } EXPORT_SYMBOL_GPL(xpc_clear_interface); @@ -123,13 +123,13 @@ EXPORT_SYMBOL_GPL(xpc_clear_interface); * nentries - max #of XPC message entries a message queue can contain. * The actual number, which is determined when a connection * is established and may be less then requested, will be - * passed to the user via the xpcConnected callout. + * passed to the user via the xpConnected callout. * assigned_limit - max number of kthreads allowed to be processing * messages (per connection) at any given instant. * idle_limit - max number of kthreads allowed to be idle at any given * instant. */ -enum xpc_retval +enum xp_retval xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size, u16 nentries, u32 assigned_limit, u32 idle_limit) { @@ -143,12 +143,12 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size, registration = &xpc_registrations[ch_number]; if (mutex_lock_interruptible(®istration->mutex) != 0) - return xpcInterrupted; + return xpInterrupted; /* if XPC_CHANNEL_REGISTERED(ch_number) */ if (registration->func != NULL) { mutex_unlock(®istration->mutex); - return xpcAlreadyRegistered; + return xpAlreadyRegistered; } /* register the channel for connection */ @@ -163,7 +163,7 @@ xpc_connect(int ch_number, xpc_channel_func func, void *key, u16 payload_size, xpc_interface.connect(ch_number); - return xpcSuccess; + return xpSuccess; } EXPORT_SYMBOL_GPL(xpc_connect); diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h index 9eb6d4a..67b179a 100644 --- a/drivers/misc/sgi-xp/xpc.h +++ b/drivers/misc/sgi-xp/xpc.h @@ -412,7 +412,7 @@ struct xpc_channel { spinlock_t lock; /* lock for updating this structure */ u32 flags; /* general flags */ - enum xpc_retval reason; /* reason why channel is disconnect'g */ + enum xp_retval reason; /* reason why channel is disconnect'g */ int reason_line; /* line# disconnect initiated from */ u16 number; /* channel # */ @@ -522,7 +522,7 @@ struct xpc_partition { spinlock_t act_lock; /* protect updating of act_state */ u8 act_state; /* from XPC HB viewpoint */ u8 remote_vars_version; /* version# of partition's vars */ - enum xpc_retval reason; /* reason partition is deactivating */ + enum xp_retval reason; /* reason partition is deactivating */ int reason_line; /* line# deactivation initiated from */ int reactivate_nasid; /* nasid in partition to reactivate */ @@ -646,31 +646,31 @@ extern void xpc_allow_IPI_ops(void); extern void xpc_restrict_IPI_ops(void); extern int xpc_identify_act_IRQ_sender(void); extern int xpc_partition_disengaged(struct xpc_partition *); -extern enum xpc_retval xpc_mark_partition_active(struct xpc_partition *); +extern enum xp_retval xpc_mark_partition_active(struct xpc_partition *); extern void xpc_mark_partition_inactive(struct xpc_partition *); extern void xpc_discovery(void); extern void xpc_check_remote_hb(void); extern void xpc_deactivate_partition(const int, struct xpc_partition *, - enum xpc_retval); -extern enum xpc_retval xpc_initiate_partid_to_nasids(partid_t, void *); + enum xp_retval); +extern enum xp_retval xpc_initiate_partid_to_nasids(partid_t, void *); /* found in xpc_channel.c */ extern void xpc_initiate_connect(int); extern void xpc_initiate_disconnect(int); -extern enum xpc_retval xpc_initiate_allocate(partid_t, int, u32, void **); -extern enum xpc_retval xpc_initiate_send(partid_t, int, void *); -extern enum xpc_retval xpc_initiate_send_notify(partid_t, int, void *, - xpc_notify_func, void *); +extern enum xp_retval xpc_initiate_allocate(partid_t, int, u32, void **); +extern enum xp_retval xpc_initiate_send(partid_t, int, void *); +extern enum xp_retval xpc_initiate_send_notify(partid_t, int, void *, + xpc_notify_func, void *); extern void xpc_initiate_received(partid_t, int, void *); -extern enum xpc_retval xpc_setup_infrastructure(struct xpc_partition *); -extern enum xpc_retval xpc_pull_remote_vars_part(struct xpc_partition *); +extern enum xp_retval xpc_setup_infrastructure(struct xpc_partition *); +extern enum xp_retval xpc_pull_remote_vars_part(struct xpc_partition *); extern void xpc_process_channel_activity(struct xpc_partition *); extern void xpc_connected_callout(struct xpc_channel *); extern void xpc_deliver_msg(struct xpc_channel *); extern void xpc_disconnect_channel(const int, struct xpc_channel *, - enum xpc_retval, unsigned long *); -extern void xpc_disconnect_callout(struct xpc_channel *, enum xpc_retval); -extern void xpc_partition_going_down(struct xpc_partition *, enum xpc_retval); + enum xp_retval, unsigned long *); +extern void xpc_disconnect_callout(struct xpc_channel *, enum xp_retval); +extern void xpc_partition_going_down(struct xpc_partition *, enum xp_retval); extern void xpc_teardown_infrastructure(struct xpc_partition *); static inline void @@ -901,7 +901,7 @@ xpc_IPI_receive(AMO_t *amo) return FETCHOP_LOAD_OP(TO_AMO((u64)&amo->variable), FETCHOP_CLEAR); } -static inline enum xpc_retval +static inline enum xp_retval xpc_IPI_send(AMO_t *amo, u64 flag, int nasid, int phys_cpuid, int vector) { int ret = 0; @@ -923,7 +923,7 @@ xpc_IPI_send(AMO_t *amo, u64 flag, int nasid, int phys_cpuid, int vector) local_irq_restore(irq_flags); - return ((ret == 0) ? xpcSuccess : xpcPioReadError); + return ((ret == 0) ? xpSuccess : xpPioReadError); } /* @@ -992,7 +992,7 @@ xpc_notify_IRQ_send(struct xpc_channel *ch, u8 ipi_flag, char *ipi_flag_string, unsigned long *irq_flags) { struct xpc_partition *part = &xpc_partitions[ch->partid]; - enum xpc_retval ret; + enum xp_retval ret; if (likely(part->act_state != XPC_P_DEACTIVATING)) { ret = xpc_IPI_send(part->remote_IPI_amo_va, @@ -1001,7 +1001,7 @@ xpc_notify_IRQ_send(struct xpc_channel *ch, u8 ipi_flag, char *ipi_flag_string, part->remote_IPI_phys_cpuid, SGI_XPC_NOTIFY); dev_dbg(xpc_chan, "%s sent to partid=%d, channel=%d, ret=%d\n", ipi_flag_string, ch->partid, ch->number, ret); - if (unlikely(ret != xpcSuccess)) { + if (unlikely(ret != xpSuccess)) { if (irq_flags != NULL) spin_unlock_irqrestore(&ch->lock, *irq_flags); XPC_DEACTIVATE_PARTITION(part, ret); @@ -1123,41 +1123,10 @@ xpc_IPI_init(int index) return amo; } -static inline enum xpc_retval +static inline enum xp_retval xpc_map_bte_errors(bte_result_t error) { - if (error == BTE_SUCCESS) - return xpcSuccess; - - if (is_shub2()) { - if (BTE_VALID_SH2_ERROR(error)) - return xpcBteSh2Start + error; - return xpcBteUnmappedError; - } - switch (error) { - case BTE_SUCCESS: - return xpcSuccess; - case BTEFAIL_DIR: - return xpcBteDirectoryError; - case BTEFAIL_POISON: - return xpcBtePoisonError; - case BTEFAIL_WERR: - return xpcBteWriteError; - case BTEFAIL_ACCESS: - return xpcBteAccessError; - case BTEFAIL_PWERR: - return xpcBtePWriteError; - case BTEFAIL_PRERR: - return xpcBtePReadError; - case BTEFAIL_TOUT: - return xpcBteTimeOutError; - case BTEFAIL_XTERR: - return xpcBteXtalkError; - case BTEFAIL_NOTAVAIL: - return xpcBteNotAvailable; - default: - return xpcBteUnmappedError; - } + return ((error == BTE_SUCCESS) ? xpSuccess : xpBteCopyError); } /* diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c index bfcb9ea..74ec506 100644 --- a/drivers/misc/sgi-xp/xpc_channel.c +++ b/drivers/misc/sgi-xp/xpc_channel.c @@ -90,7 +90,7 @@ xpc_initialize_channels(struct xpc_partition *part, partid_t partid) * Setup the infrastructure necessary to support XPartition Communication * between the specified remote partition and the local one. */ -enum xpc_retval +enum xp_retval xpc_setup_infrastructure(struct xpc_partition *part) { int ret, cpuid; @@ -114,7 +114,7 @@ xpc_setup_infrastructure(struct xpc_partition *part) GFP_KERNEL); if (part->channels == NULL) { dev_err(xpc_chan, "can't get memory for channels\n"); - return xpcNoMemory; + return xpNoMemory; } part->nchannels = XPC_NCHANNELS; @@ -129,7 +129,7 @@ xpc_setup_infrastructure(struct xpc_partition *part) part->channels = NULL; dev_err(xpc_chan, "can't get memory for local get/put " "values\n"); - return xpcNoMemory; + return xpNoMemory; } part->remote_GPs = xpc_kzalloc_cacheline_aligned(XPC_GP_SIZE, @@ -143,7 +143,7 @@ xpc_setup_infrastructure(struct xpc_partition *part) part->local_GPs = NULL; kfree(part->channels); part->channels = NULL; - return xpcNoMemory; + return xpNoMemory; } /* allocate all the required open and close args */ @@ -159,7 +159,7 @@ xpc_setup_infrastructure(struct xpc_partition *part) part->local_GPs = NULL; kfree(part->channels); part->channels = NULL; - return xpcNoMemory; + return xpNoMemory; } part->remote_openclose_args = @@ -175,7 +175,7 @@ xpc_setup_infrastructure(struct xpc_partition *part) part->local_GPs = NULL; kfree(part->channels); part->channels = NULL; - return xpcNoMemory; + return xpNoMemory; } xpc_initialize_channels(part, partid); @@ -209,7 +209,7 @@ xpc_setup_infrastructure(struct xpc_partition *part) part->local_GPs = NULL; kfree(part->channels); part->channels = NULL; - return xpcLackOfResources; + return xpLackOfResources; } /* Setup a timer to check for dropped IPIs */ @@ -243,7 +243,7 @@ xpc_setup_infrastructure(struct xpc_partition *part) xpc_vars_part[partid].nchannels = part->nchannels; xpc_vars_part[partid].magic = XPC_VP_MAGIC1; - return xpcSuccess; + return xpSuccess; } /* @@ -254,7 +254,7 @@ xpc_setup_infrastructure(struct xpc_partition *part) * dst must be a cacheline aligned virtual address on this partition. * cnt must be an cacheline sized */ -static enum xpc_retval +static enum xp_retval xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst, const void *src, size_t cnt) { @@ -270,7 +270,7 @@ xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst, bte_ret = xp_bte_copy((u64)src, (u64)dst, (u64)cnt, (BTE_NORMAL | BTE_WACQUIRE), NULL); if (bte_ret == BTE_SUCCESS) - return xpcSuccess; + return xpSuccess; dev_dbg(xpc_chan, "xp_bte_copy() from partition %d failed, ret=%d\n", XPC_PARTID(part), bte_ret); @@ -282,7 +282,7 @@ xpc_pull_remote_cachelines(struct xpc_partition *part, void *dst, * Pull the remote per partition specific variables from the specified * partition. */ -enum xpc_retval +enum xp_retval xpc_pull_remote_vars_part(struct xpc_partition *part) { u8 buffer[L1_CACHE_BYTES * 2]; @@ -291,7 +291,7 @@ xpc_pull_remote_vars_part(struct xpc_partition *part) struct xpc_vars_part *pulled_entry; u64 remote_entry_cacheline_pa, remote_entry_pa; partid_t partid = XPC_PARTID(part); - enum xpc_retval ret; + enum xp_retval ret; /* pull the cacheline that contains the variables we're interested in */ @@ -311,7 +311,7 @@ xpc_pull_remote_vars_part(struct xpc_partition *part) ret = xpc_pull_remote_cachelines(part, pulled_entry_cacheline, (void *)remote_entry_cacheline_pa, L1_CACHE_BYTES); - if (ret != xpcSuccess) { + if (ret != xpSuccess) { dev_dbg(xpc_chan, "failed to pull XPC vars_part from " "partition %d, ret=%d\n", partid, ret); return ret; @@ -326,11 +326,11 @@ xpc_pull_remote_vars_part(struct xpc_partition *part) dev_dbg(xpc_chan, "partition %d's XPC vars_part for " "partition %d has bad magic value (=0x%lx)\n", partid, sn_partition_id, pulled_entry->magic); - return xpcBadMagic; + return xpBadMagic; } /* they've not been initialized yet */ - return xpcRetry; + return xpRetry; } if (xpc_vars_part[partid].magic == XPC_VP_MAGIC1) { @@ -344,7 +344,7 @@ xpc_pull_remote_vars_part(struct xpc_partition *part) dev_err(xpc_chan, "partition %d's XPC vars_part for " "partition %d are not valid\n", partid, sn_partition_id); - return xpcInvalidAddress; + return xpInvalidAddress; } /* the variables we imported look to be valid */ @@ -366,9 +366,9 @@ xpc_pull_remote_vars_part(struct xpc_partition *part) } if (pulled_entry->magic == XPC_VP_MAGIC1) - return xpcRetry; + return xpRetry; - return xpcSuccess; + return xpSuccess; } /* @@ -379,7 +379,7 @@ xpc_get_IPI_flags(struct xpc_partition *part) { unsigned long irq_flags; u64 IPI_amo; - enum xpc_retval ret; + enum xp_retval ret; /* * See if there are any IPI flags to be handled. @@ -398,7 +398,7 @@ xpc_get_IPI_flags(struct xpc_partition *part) (void *)part-> remote_openclose_args_pa, XPC_OPENCLOSE_ARGS_SIZE); - if (ret != xpcSuccess) { + if (ret != xpSuccess) { XPC_DEACTIVATE_PARTITION(part, ret); dev_dbg(xpc_chan, "failed to pull openclose args from " @@ -414,7 +414,7 @@ xpc_get_IPI_flags(struct xpc_partition *part) ret = xpc_pull_remote_cachelines(part, part->remote_GPs, (void *)part->remote_GPs_pa, XPC_GP_SIZE); - if (ret != xpcSuccess) { + if (ret != xpSuccess) { XPC_DEACTIVATE_PARTITION(part, ret); dev_dbg(xpc_chan, "failed to pull GPs from partition " @@ -431,7 +431,7 @@ xpc_get_IPI_flags(struct xpc_partition *part) /* * Allocate the local message queue and the notify queue. */ -static enum xpc_retval +static enum xp_retval xpc_allocate_local_msgqueue(struct xpc_channel *ch) { unsigned long irq_flags; @@ -464,18 +464,18 @@ xpc_allocate_local_msgqueue(struct xpc_channel *ch) ch->local_nentries = nentries; } spin_unlock_irqrestore(&ch->lock, irq_flags); - return xpcSuccess; + return xpSuccess; } dev_dbg(xpc_chan, "can't get memory for local message queue and notify " "queue, partid=%d, channel=%d\n", ch->partid, ch->number); - return xpcNoMemory; + return xpNoMemory; } /* * Allocate the cached remote message queue. */ -static enum xpc_retval +static enum xp_retval xpc_allocate_remote_msgqueue(struct xpc_channel *ch) { unsigned long irq_flags; @@ -502,12 +502,12 @@ xpc_allocate_remote_msgqueue(struct xpc_channel *ch) ch->remote_nentries = nentries; } spin_unlock_irqrestore(&ch->lock, irq_flags); - return xpcSuccess; + return xpSuccess; } dev_dbg(xpc_chan, "can't get memory for cached remote message queue, " "partid=%d, channel=%d\n", ch->partid, ch->number); - return xpcNoMemory; + return xpNoMemory; } /* @@ -515,20 +515,20 @@ xpc_allocate_remote_msgqueue(struct xpc_channel *ch) * * Note: Assumes all of the channel sizes are filled in. */ -static enum xpc_retval +static enum xp_retval xpc_allocate_msgqueues(struct xpc_channel *ch) { unsigned long irq_flags; - enum xpc_retval ret; + enum xp_retval ret; DBUG_ON(ch->flags & XPC_C_SETUP); ret = xpc_allocate_local_msgqueue(ch); - if (ret != xpcSuccess) + if (ret != xpSuccess) return ret; ret = xpc_allocate_remote_msgqueue(ch); - if (ret != xpcSuccess) { + if (ret != xpSuccess) { kfree(ch->local_msgqueue_base); ch->local_msgqueue = NULL; kfree(ch->notify_queue); @@ -540,7 +540,7 @@ xpc_allocate_msgqueues(struct xpc_channel *ch) ch->flags |= XPC_C_SETUP; spin_unlock_irqrestore(&ch->lock, irq_flags); - return xpcSuccess; + return xpSuccess; } /* @@ -552,7 +552,7 @@ xpc_allocate_msgqueues(struct xpc_channel *ch) static void xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags) { - enum xpc_retval ret; + enum xp_retval ret; DBUG_ON(!spin_is_locked(&ch->lock)); @@ -568,7 +568,7 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags) ret = xpc_allocate_msgqueues(ch); spin_lock_irqsave(&ch->lock, *irq_flags); - if (ret != xpcSuccess) + if (ret != xpSuccess) XPC_DISCONNECT_CHANNEL(ch, ret, irq_flags); if (ch->flags & (XPC_C_CONNECTED | XPC_C_DISCONNECTING)) @@ -603,7 +603,7 @@ xpc_process_connect(struct xpc_channel *ch, unsigned long *irq_flags) * Notify those who wanted to be notified upon delivery of their message. */ static void -xpc_notify_senders(struct xpc_channel *ch, enum xpc_retval reason, s64 put) +xpc_notify_senders(struct xpc_channel *ch, enum xp_retval reason, s64 put) { struct xpc_notify *notify; u8 notify_type; @@ -748,7 +748,7 @@ xpc_process_disconnect(struct xpc_channel *ch, unsigned long *irq_flags) if (ch->flags & XPC_C_DISCONNECTINGCALLOUT_MADE) { spin_unlock_irqrestore(&ch->lock, *irq_flags); - xpc_disconnect_callout(ch, xpcDisconnected); + xpc_disconnect_callout(ch, xpDisconnected); spin_lock_irqsave(&ch->lock, *irq_flags); } @@ -791,7 +791,7 @@ xpc_process_openclose_IPI(struct xpc_partition *part, int ch_number, struct xpc_openclose_args *args = &part->remote_openclose_args[ch_number]; struct xpc_channel *ch = &part->channels[ch_number]; - enum xpc_retval reason; + enum xp_retval reason; spin_lock_irqsave(&ch->lock, irq_flags); @@ -871,10 +871,10 @@ again: if (!(ch->flags & XPC_C_DISCONNECTING)) { reason = args->reason; - if (reason <= xpcSuccess || reason > xpcUnknownReason) - reason = xpcUnknownReason; - else if (reason == xpcUnregistering) - reason = xpcOtherUnregistering; + if (reason <= xpSuccess || reason > xpUnknownReason) + reason = xpUnknownReason; + else if (reason == xpUnregistering) + reason = xpOtherUnregistering; XPC_DISCONNECT_CHANNEL(ch, reason, &irq_flags); @@ -961,7 +961,7 @@ again: if (ch->flags & XPC_C_OPENREQUEST) { if (args->msg_size != ch->msg_size) { - XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes, + XPC_DISCONNECT_CHANNEL(ch, xpUnequalMsgSizes, &irq_flags); spin_unlock_irqrestore(&ch->lock, irq_flags); return; @@ -991,7 +991,7 @@ again: return; } if (!(ch->flags & XPC_C_OPENREQUEST)) { - XPC_DISCONNECT_CHANNEL(ch, xpcOpenCloseError, + XPC_DISCONNECT_CHANNEL(ch, xpOpenCloseError, &irq_flags); spin_unlock_irqrestore(&ch->lock, irq_flags); return; @@ -1042,18 +1042,18 @@ again: /* * Attempt to establish a channel connection to a remote partition. */ -static enum xpc_retval +static enum xp_retval xpc_connect_channel(struct xpc_channel *ch) { unsigned long irq_flags; struct xpc_registration *registration = &xpc_registrations[ch->number]; if (mutex_trylock(®istration->mutex) == 0) - return xpcRetry; + return xpRetry; if (!XPC_CHANNEL_REGISTERED(ch->number)) { mutex_unlock(®istration->mutex); - return xpcUnregistered; + return xpUnregistered; } spin_lock_irqsave(&ch->lock, irq_flags); @@ -1095,10 +1095,10 @@ xpc_connect_channel(struct xpc_channel *ch) * the channel lock as needed. */ mutex_unlock(®istration->mutex); - XPC_DISCONNECT_CHANNEL(ch, xpcUnequalMsgSizes, + XPC_DISCONNECT_CHANNEL(ch, xpUnequalMsgSizes, &irq_flags); spin_unlock_irqrestore(&ch->lock, irq_flags); - return xpcUnequalMsgSizes; + return xpUnequalMsgSizes; } } else { ch->msg_size = registration->msg_size; @@ -1120,7 +1120,7 @@ xpc_connect_channel(struct xpc_channel *ch) spin_unlock_irqrestore(&ch->lock, irq_flags); - return xpcSuccess; + return xpSuccess; } /* @@ -1203,7 +1203,7 @@ xpc_process_msg_IPI(struct xpc_partition *part, int ch_number) * Notify senders that messages sent have been * received and delivered by the other side. */ - xpc_notify_senders(ch, xpcMsgDelivered, + xpc_notify_senders(ch, xpMsgDelivered, ch->remote_GP.get); } @@ -1335,7 +1335,7 @@ xpc_process_channel_activity(struct xpc_partition *part) * at the same time. */ void -xpc_partition_going_down(struct xpc_partition *part, enum xpc_retval reason) +xpc_partition_going_down(struct xpc_partition *part, enum xp_retval reason) { unsigned long irq_flags; int ch_number; @@ -1456,13 +1456,13 @@ xpc_connected_callout(struct xpc_channel *ch) /* let the registerer know that a connection has been established */ if (ch->func != NULL) { - dev_dbg(xpc_chan, "ch->func() called, reason=xpcConnected, " + dev_dbg(xpc_chan, "ch->func() called, reason=xpConnected, " "partid=%d, channel=%d\n", ch->partid, ch->number); - ch->func(xpcConnected, ch->partid, ch->number, + ch->func(xpConnected, ch->partid, ch->number, (void *)(u64)ch->local_nentries, ch->key); - dev_dbg(xpc_chan, "ch->func() returned, reason=xpcConnected, " + dev_dbg(xpc_chan, "ch->func() returned, reason=xpConnected, " "partid=%d, channel=%d\n", ch->partid, ch->number); } } @@ -1503,7 +1503,7 @@ xpc_initiate_disconnect(int ch_number) if (!(ch->flags & XPC_C_DISCONNECTED)) { ch->flags |= XPC_C_WDISCONNECT; - XPC_DISCONNECT_CHANNEL(ch, xpcUnregistering, + XPC_DISCONNECT_CHANNEL(ch, xpUnregistering, &irq_flags); } @@ -1528,7 +1528,7 @@ xpc_initiate_disconnect(int ch_number) */ void xpc_disconnect_channel(const int line, struct xpc_channel *ch, - enum xpc_retval reason, unsigned long *irq_flags) + enum xp_retval reason, unsigned long *irq_flags) { u32 channel_was_connected = (ch->flags & XPC_C_CONNECTED); @@ -1563,7 +1563,7 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch, } else if ((ch->flags & XPC_C_CONNECTEDCALLOUT_MADE) && !(ch->flags & XPC_C_DISCONNECTINGCALLOUT)) { - /* start a kthread that will do the xpcDisconnecting callout */ + /* start a kthread that will do the xpDisconnecting callout */ xpc_create_kthreads(ch, 1, 1); } @@ -1575,7 +1575,7 @@ xpc_disconnect_channel(const int line, struct xpc_channel *ch, } void -xpc_disconnect_callout(struct xpc_channel *ch, enum xpc_retval reason) +xpc_disconnect_callout(struct xpc_channel *ch, enum xp_retval reason) { /* * Let the channel's registerer know that the channel is being @@ -1598,13 +1598,13 @@ xpc_disconnect_callout(struct xpc_channel *ch, enum xpc_retval reason) * Wait for a message entry to become available for the specified channel, * but don't wait any longer than 1 jiffy. */ -static enum xpc_retval +static enum xp_retval xpc_allocate_msg_wait(struct xpc_channel *ch) { - enum xpc_retval ret; + enum xp_retval ret; if (ch->flags & XPC_C_DISCONNECTING) { - DBUG_ON(ch->reason == xpcInterrupted); + DBUG_ON(ch->reason == xpInterrupted); return ch->reason; } @@ -1614,11 +1614,11 @@ xpc_allocate_msg_wait(struct xpc_channel *ch) if (ch->flags & XPC_C_DISCONNECTING) { ret = ch->reason; - DBUG_ON(ch->reason == xpcInterrupted); + DBUG_ON(ch->reason == xpInterrupted); } else if (ret == 0) { - ret = xpcTimeout; + ret = xpTimeout; } else { - ret = xpcInterrupted; + ret = xpInterrupted; } return ret; @@ -1628,12 +1628,12 @@ xpc_allocate_msg_wait(struct xpc_channel *ch) * Allocate an entry for a message from the message queue associated with the * specified channel. */ -static enum xpc_retval +static enum xp_retval xpc_allocate_msg(struct xpc_channel *ch, u32 flags, struct xpc_msg **address_of_msg) { struct xpc_msg *msg; - enum xpc_retval ret; + enum xp_retval ret; s64 put; /* this reference will be dropped in xpc_send_msg() */ @@ -1645,7 +1645,7 @@ xpc_allocate_msg(struct xpc_channel *ch, u32 flags, } if (!(ch->flags & XPC_C_CONNECTED)) { xpc_msgqueue_deref(ch); - return xpcNotConnected; + return xpNotConnected; } /* @@ -1653,7 +1653,7 @@ xpc_allocate_msg(struct xpc_channel *ch, u32 flags, * If none are available, we'll make sure that we grab the latest * GP values. */ - ret = xpcTimeout; + ret = xpTimeout; while (1) { @@ -1683,16 +1683,16 @@ xpc_allocate_msg(struct xpc_channel *ch, u32 flags, * that will cause the IPI handler to fetch the latest * GP values as if an IPI was sent by the other side. */ - if (ret == xpcTimeout) + if (ret == xpTimeout) xpc_IPI_send_local_msgrequest(ch); if (flags & XPC_NOWAIT) { xpc_msgqueue_deref(ch); - return xpcNoWait; + return xpNoWait; } ret = xpc_allocate_msg_wait(ch); - if (ret != xpcInterrupted && ret != xpcTimeout) { + if (ret != xpInterrupted && ret != xpTimeout) { xpc_msgqueue_deref(ch); return ret; } @@ -1711,7 +1711,7 @@ xpc_allocate_msg(struct xpc_channel *ch, u32 flags, *address_of_msg = msg; - return xpcSuccess; + return xpSuccess; } /* @@ -1727,11 +1727,11 @@ xpc_allocate_msg(struct xpc_channel *ch, u32 flags, * payload - address of the allocated payload area pointer (filled in on * return) in which the user-defined message is constructed. */ -enum xpc_retval +enum xp_retval xpc_initiate_allocate(partid_t partid, int ch_number, u32 flags, void **payload) { struct xpc_partition *part = &xpc_partitions[partid]; - enum xpc_retval ret = xpcUnknownReason; + enum xp_retval ret = xpUnknownReason; struct xpc_msg *msg = NULL; DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS); @@ -1814,11 +1814,11 @@ xpc_send_msgs(struct xpc_channel *ch, s64 initial_put) * local message queue's Put value and sends an IPI to the partition the * message is being sent to. */ -static enum xpc_retval +static enum xp_retval xpc_send_msg(struct xpc_channel *ch, struct xpc_msg *msg, u8 notify_type, xpc_notify_func func, void *key) { - enum xpc_retval ret = xpcSuccess; + enum xp_retval ret = xpSuccess; struct xpc_notify *notify = notify; s64 put, msg_number = msg->number; @@ -1908,12 +1908,12 @@ xpc_send_msg(struct xpc_channel *ch, struct xpc_msg *msg, u8 notify_type, * payload - pointer to the payload area allocated via * xpc_initiate_allocate(). */ -enum xpc_retval +enum xp_retval xpc_initiate_send(partid_t partid, int ch_number, void *payload) { struct xpc_partition *part = &xpc_partitions[partid]; struct xpc_msg *msg = XPC_MSG_ADDRESS(payload); - enum xpc_retval ret; + enum xp_retval ret; dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *)msg, partid, ch_number); @@ -1957,13 +1957,13 @@ xpc_initiate_send(partid_t partid, int ch_number, void *payload) * receipt. THIS FUNCTION MUST BE NON-BLOCKING. * key - user-defined key to be passed to the function when it's called. */ -enum xpc_retval +enum xp_retval xpc_initiate_send_notify(partid_t partid, int ch_number, void *payload, xpc_notify_func func, void *key) { struct xpc_partition *part = &xpc_partitions[partid]; struct xpc_msg *msg = XPC_MSG_ADDRESS(payload); - enum xpc_retval ret; + enum xp_retval ret; dev_dbg(xpc_chan, "msg=0x%p, partid=%d, channel=%d\n", (void *)msg, partid, ch_number); @@ -1985,7 +1985,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get) struct xpc_msg *remote_msg, *msg; u32 msg_index, nmsgs; u64 msg_offset; - enum xpc_retval ret; + enum xp_retval ret; if (mutex_lock_interruptible(&ch->msg_to_pull_mutex) != 0) { /* we were interrupted by a signal */ @@ -2012,7 +2012,7 @@ xpc_pull_remote_msg(struct xpc_channel *ch, s64 get) ret = xpc_pull_remote_cachelines(part, msg, remote_msg, nmsgs * ch->msg_size); - if (ret != xpcSuccess) { + if (ret != xpSuccess) { dev_dbg(xpc_chan, "failed to pull %d msgs starting with" " msg %ld from partition %d, channel=%d, " @@ -2112,7 +2112,7 @@ xpc_deliver_msg(struct xpc_channel *ch) ch->number); /* deliver the message to its intended recipient */ - ch->func(xpcMsgReceived, ch->partid, ch->number, + ch->func(xpMsgReceived, ch->partid, ch->number, &msg->payload, ch->key); dev_dbg(xpc_chan, "ch->func() returned, msg=0x%p, " diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index f673ba9..2765b42 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c @@ -315,13 +315,13 @@ xpc_initiate_discovery(void *ignore) * the XPC per partition variables from the remote partition and waiting for * the remote partition to pull ours. */ -static enum xpc_retval +static enum xp_retval xpc_make_first_contact(struct xpc_partition *part) { - enum xpc_retval ret; + enum xp_retval ret; - while ((ret = xpc_pull_remote_vars_part(part)) != xpcSuccess) { - if (ret != xpcRetry) { + while ((ret = xpc_pull_remote_vars_part(part)) != xpSuccess) { + if (ret != xpRetry) { XPC_DEACTIVATE_PARTITION(part, ret); return ret; } @@ -406,7 +406,7 @@ xpc_partition_up(struct xpc_partition *part) dev_dbg(xpc_chan, "activating partition %d\n", XPC_PARTID(part)); - if (xpc_setup_infrastructure(part) != xpcSuccess) + if (xpc_setup_infrastructure(part) != xpSuccess) return; /* @@ -418,7 +418,7 @@ xpc_partition_up(struct xpc_partition *part) (void)xpc_part_ref(part); /* this will always succeed */ - if (xpc_make_first_contact(part) == xpcSuccess) + if (xpc_make_first_contact(part) == xpSuccess) xpc_channel_mgr(part); xpc_part_deref(part); @@ -470,7 +470,7 @@ xpc_activating(void *__partid) spin_lock_irqsave(&part->act_lock, irq_flags); part->act_state = XPC_P_INACTIVE; - XPC_SET_REASON(part, xpcPhysAddrRegFailed, __LINE__); + XPC_SET_REASON(part, xpPhysAddrRegFailed, __LINE__); spin_unlock_irqrestore(&part->act_lock, irq_flags); part->remote_rp_pa = 0; return 0; @@ -488,7 +488,7 @@ xpc_activating(void *__partid) xpc_disallow_hb(partid, xpc_vars); xpc_mark_partition_inactive(part); - if (part->reason == xpcReactivating) { + if (part->reason == xpReactivating) { /* interrupting ourselves results in activating partition */ xpc_IPI_send_reactivate(part); } @@ -508,7 +508,7 @@ xpc_activate_partition(struct xpc_partition *part) DBUG_ON(part->act_state != XPC_P_INACTIVE); part->act_state = XPC_P_ACTIVATION_REQ; - XPC_SET_REASON(part, xpcCloneKThread, __LINE__); + XPC_SET_REASON(part, xpCloneKThread, __LINE__); spin_unlock_irqrestore(&part->act_lock, irq_flags); @@ -517,7 +517,7 @@ xpc_activate_partition(struct xpc_partition *part) if (IS_ERR(kthread)) { spin_lock_irqsave(&part->act_lock, irq_flags); part->act_state = XPC_P_INACTIVE; - XPC_SET_REASON(part, xpcCloneKThreadFailed, __LINE__); + XPC_SET_REASON(part, xpCloneKThreadFailed, __LINE__); spin_unlock_irqrestore(&part->act_lock, irq_flags); } } @@ -696,7 +696,7 @@ xpc_kthread_start(void *args) ch->flags |= XPC_C_DISCONNECTINGCALLOUT; spin_unlock_irqrestore(&ch->lock, irq_flags); - xpc_disconnect_callout(ch, xpcDisconnecting); + xpc_disconnect_callout(ch, xpDisconnecting); spin_lock_irqsave(&ch->lock, irq_flags); ch->flags |= XPC_C_DISCONNECTINGCALLOUT_MADE; @@ -776,7 +776,7 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed, * then we'll deadlock if all other kthreads assigned * to this channel are blocked in the channel's * registerer, because the only thing that will unblock - * them is the xpcDisconnecting callout that this + * them is the xpDisconnecting callout that this * failed kthread_run() would have made. */ @@ -796,7 +796,7 @@ xpc_create_kthreads(struct xpc_channel *ch, int needed, * to function. */ spin_lock_irqsave(&ch->lock, irq_flags); - XPC_DISCONNECT_CHANNEL(ch, xpcLackOfResources, + XPC_DISCONNECT_CHANNEL(ch, xpLackOfResources, &irq_flags); spin_unlock_irqrestore(&ch->lock, irq_flags); } @@ -857,7 +857,7 @@ xpc_disconnect_wait(int ch_number) } static void -xpc_do_exit(enum xpc_retval reason) +xpc_do_exit(enum xp_retval reason) { partid_t partid; int active_part_count, printed_waiting_msg = 0; @@ -955,7 +955,7 @@ xpc_do_exit(enum xpc_retval reason) del_timer_sync(&xpc_hb_timer); DBUG_ON(xpc_vars->heartbeating_to_mask != 0); - if (reason == xpcUnloading) { + if (reason == xpUnloading) { /* take ourselves off of the reboot_notifier_list */ (void)unregister_reboot_notifier(&xpc_reboot_notifier); @@ -981,20 +981,20 @@ xpc_do_exit(enum xpc_retval reason) static int xpc_system_reboot(struct notifier_block *nb, unsigned long event, void *unused) { - enum xpc_retval reason; + enum xp_retval reason; switch (event) { case SYS_RESTART: - reason = xpcSystemReboot; + reason = xpSystemReboot; break; case SYS_HALT: - reason = xpcSystemHalt; + reason = xpSystemHalt; break; case SYS_POWER_OFF: - reason = xpcSystemPoweroff; + reason = xpSystemPoweroff; break; default: - reason = xpcSystemGoingDown; + reason = xpSystemGoingDown; } xpc_do_exit(reason); @@ -1279,7 +1279,7 @@ xpc_init(void) /* mark this new thread as a non-starter */ complete(&xpc_discovery_exited); - xpc_do_exit(xpcUnloading); + xpc_do_exit(xpUnloading); return -EBUSY; } @@ -1297,7 +1297,7 @@ module_init(xpc_init); void __exit xpc_exit(void) { - xpc_do_exit(xpcUnloading); + xpc_do_exit(xpUnloading); } module_exit(xpc_exit); diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c index acd3fd4..d9b462e 100644 --- a/drivers/misc/sgi-xp/xpc_partition.c +++ b/drivers/misc/sgi-xp/xpc_partition.c @@ -444,7 +444,7 @@ xpc_check_remote_hb(void) (remote_vars->heartbeat_offline == 0)) || !xpc_hb_allowed(sn_partition_id, remote_vars)) { - XPC_DEACTIVATE_PARTITION(part, xpcNoHeartbeat); + XPC_DEACTIVATE_PARTITION(part, xpNoHeartbeat); continue; } @@ -459,7 +459,7 @@ xpc_check_remote_hb(void) * is large enough to contain a copy of their reserved page header and * part_nasids mask. */ -static enum xpc_retval +static enum xp_retval xpc_get_remote_rp(int nasid, u64 *discovered_nasids, struct xpc_rsvd_page *remote_rp, u64 *remote_rp_pa) { @@ -469,7 +469,7 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids, *remote_rp_pa = xpc_get_rsvd_page_pa(nasid); if (*remote_rp_pa == 0) - return xpcNoRsvdPageAddr; + return xpNoRsvdPageAddr; /* pull over the reserved page header and part_nasids mask */ bres = xp_bte_copy(*remote_rp_pa, (u64)remote_rp, @@ -489,18 +489,18 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids, if (remote_rp->partid < 1 || remote_rp->partid > (XP_MAX_PARTITIONS - 1)) { - return xpcInvalidPartid; + return xpInvalidPartid; } if (remote_rp->partid == sn_partition_id) - return xpcLocalPartid; + return xpLocalPartid; if (XPC_VERSION_MAJOR(remote_rp->version) != XPC_VERSION_MAJOR(XPC_RP_VERSION)) { - return xpcBadVersion; + return xpBadVersion; } - return xpcSuccess; + return xpSuccess; } /* @@ -509,13 +509,13 @@ xpc_get_remote_rp(int nasid, u64 *discovered_nasids, * remote_vars points to a buffer that is cacheline aligned for BTE copies and * assumed to be of size XPC_RP_VARS_SIZE. */ -static enum xpc_retval +static enum xp_retval xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars) { int bres; if (remote_vars_pa == 0) - return xpcVarsNotSet; + return xpVarsNotSet; /* pull over the cross partition variables */ bres = xp_bte_copy(remote_vars_pa, (u64)remote_vars, XPC_RP_VARS_SIZE, @@ -525,10 +525,10 @@ xpc_get_remote_vars(u64 remote_vars_pa, struct xpc_vars *remote_vars) if (XPC_VERSION_MAJOR(remote_vars->version) != XPC_VERSION_MAJOR(XPC_V_VERSION)) { - return xpcBadVersion; + return xpBadVersion; } - return xpcSuccess; + return xpSuccess; } /* @@ -606,14 +606,14 @@ xpc_identify_act_IRQ_req(int nasid) struct timespec remote_rp_stamp = { 0, 0 }; partid_t partid; struct xpc_partition *part; - enum xpc_retval ret; + enum xp_retval ret; /* pull over the reserved page structure */ remote_rp = (struct xpc_rsvd_page *)xpc_remote_copy_buffer; ret = xpc_get_remote_rp(nasid, NULL, remote_rp, &remote_rp_pa); - if (ret != xpcSuccess) { + if (ret != xpSuccess) { dev_warn(xpc_part, "unable to get reserved page from nasid %d, " "which sent interrupt, reason=%d\n", nasid, ret); return; @@ -632,7 +632,7 @@ xpc_identify_act_IRQ_req(int nasid) remote_vars = (struct xpc_vars *)xpc_remote_copy_buffer; ret = xpc_get_remote_vars(remote_vars_pa, remote_vars); - if (ret != xpcSuccess) { + if (ret != xpSuccess) { dev_warn(xpc_part, "unable to get XPC variables from nasid %d, " "which sent interrupt, reason=%d\n", nasid, ret); @@ -699,7 +699,7 @@ xpc_identify_act_IRQ_req(int nasid) &remote_rp_stamp, remote_rp_pa, remote_vars_pa, remote_vars); part->reactivate_nasid = nasid; - XPC_DEACTIVATE_PARTITION(part, xpcReactivating); + XPC_DEACTIVATE_PARTITION(part, xpReactivating); return; } @@ -754,11 +754,11 @@ xpc_identify_act_IRQ_req(int nasid) if (reactivate) { part->reactivate_nasid = nasid; - XPC_DEACTIVATE_PARTITION(part, xpcReactivating); + XPC_DEACTIVATE_PARTITION(part, xpReactivating); } else if (XPC_SUPPORTS_DISENGAGE_REQUEST(part->remote_vars_version) && xpc_partition_disengage_requested(1UL << partid)) { - XPC_DEACTIVATE_PARTITION(part, xpcOtherGoingDown); + XPC_DEACTIVATE_PARTITION(part, xpOtherGoingDown); } } @@ -870,20 +870,20 @@ xpc_partition_disengaged(struct xpc_partition *part) /* * Mark specified partition as active. */ -enum xpc_retval +enum xp_retval xpc_mark_partition_active(struct xpc_partition *part) { unsigned long irq_flags; - enum xpc_retval ret; + enum xp_retval ret; dev_dbg(xpc_part, "setting partition %d to ACTIVE\n", XPC_PARTID(part)); spin_lock_irqsave(&part->act_lock, irq_flags); if (part->act_state == XPC_P_ACTIVATING) { part->act_state = XPC_P_ACTIVE; - ret = xpcSuccess; + ret = xpSuccess; } else { - DBUG_ON(part->reason == xpcSuccess); + DBUG_ON(part->reason == xpSuccess); ret = part->reason; } spin_unlock_irqrestore(&part->act_lock, irq_flags); @@ -896,7 +896,7 @@ xpc_mark_partition_active(struct xpc_partition *part) */ void xpc_deactivate_partition(const int line, struct xpc_partition *part, - enum xpc_retval reason) + enum xp_retval reason) { unsigned long irq_flags; @@ -905,15 +905,15 @@ xpc_deactivate_partition(const int line, struct xpc_partition *part, if (part->act_state == XPC_P_INACTIVE) { XPC_SET_REASON(part, reason, line); spin_unlock_irqrestore(&part->act_lock, irq_flags); - if (reason == xpcReactivating) { + if (reason == xpReactivating) { /* we interrupt ourselves to reactivate partition */ xpc_IPI_send_reactivate(part); } return; } if (part->act_state == XPC_P_DEACTIVATING) { - if ((part->reason == xpcUnloading && reason != xpcUnloading) || - reason == xpcReactivating) { + if ((part->reason == xpUnloading && reason != xpUnloading) || + reason == xpReactivating) { XPC_SET_REASON(part, reason, line); } spin_unlock_irqrestore(&part->act_lock, irq_flags); @@ -985,7 +985,7 @@ xpc_discovery(void) partid_t partid; struct xpc_partition *part; u64 *discovered_nasids; - enum xpc_retval ret; + enum xp_retval ret; remote_rp = xpc_kmalloc_cacheline_aligned(XPC_RP_HEADER_SIZE + xp_nasid_mask_bytes, @@ -1063,12 +1063,12 @@ xpc_discovery(void) ret = xpc_get_remote_rp(nasid, discovered_nasids, remote_rp, &remote_rp_pa); - if (ret != xpcSuccess) { + if (ret != xpSuccess) { dev_dbg(xpc_part, "unable to get reserved page " "from nasid %d, reason=%d\n", nasid, ret); - if (ret == xpcLocalPartid) + if (ret == xpLocalPartid) break; continue; @@ -1082,7 +1082,7 @@ xpc_discovery(void) /* pull over the cross partition variables */ ret = xpc_get_remote_vars(remote_vars_pa, remote_vars); - if (ret != xpcSuccess) { + if (ret != xpSuccess) { dev_dbg(xpc_part, "unable to get XPC variables " "from nasid %d, reason=%d\n", nasid, ret); @@ -1116,7 +1116,7 @@ xpc_discovery(void) "register xp_addr region 0x%016lx\n", partid, remote_vars->amos_page_pa); - XPC_SET_REASON(part, xpcPhysAddrRegFailed, + XPC_SET_REASON(part, xpPhysAddrRegFailed, __LINE__); break; } @@ -1151,7 +1151,7 @@ xpc_discovery(void) * Given a partid, get the nasids owned by that partition from the * remote partition's reserved page. */ -enum xpc_retval +enum xp_retval xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask) { struct xpc_partition *part; @@ -1160,7 +1160,7 @@ xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask) part = &xpc_partitions[partid]; if (part->remote_rp_pa == 0) - return xpcPartitionDown; + return xpPartitionDown; memset(nasid_mask, 0, XP_NASID_MASK_BYTES); diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c index a9543c6..38df166 100644 --- a/drivers/misc/sgi-xp/xpnet.c +++ b/drivers/misc/sgi-xp/xpnet.c @@ -282,7 +282,7 @@ xpnet_receive(partid_t partid, int channel, struct xpnet_message *msg) * state or message reception on a connection. */ static void -xpnet_connection_activity(enum xpc_retval reason, partid_t partid, int channel, +xpnet_connection_activity(enum xp_retval reason, partid_t partid, int channel, void *data, void *key) { long bp; @@ -291,13 +291,13 @@ xpnet_connection_activity(enum xpc_retval reason, partid_t partid, int channel, DBUG_ON(channel != XPC_NET_CHANNEL); switch (reason) { - case xpcMsgReceived: /* message received */ + case xpMsgReceived: /* message received */ DBUG_ON(data == NULL); xpnet_receive(partid, channel, (struct xpnet_message *)data); break; - case xpcConnected: /* connection completed to a partition */ + case xpConnected: /* connection completed to a partition */ spin_lock_bh(&xpnet_broadcast_lock); xpnet_broadcast_partitions |= 1UL << (partid - 1); bp = xpnet_broadcast_partitions; @@ -330,7 +330,7 @@ xpnet_connection_activity(enum xpc_retval reason, partid_t partid, int channel, static int xpnet_dev_open(struct net_device *dev) { - enum xpc_retval ret; + enum xp_retval ret; dev_dbg(xpnet, "calling xpc_connect(%d, 0x%p, NULL, %ld, %ld, %ld, " "%ld)\n", XPC_NET_CHANNEL, xpnet_connection_activity, @@ -340,7 +340,7 @@ xpnet_dev_open(struct net_device *dev) ret = xpc_connect(XPC_NET_CHANNEL, xpnet_connection_activity, NULL, XPNET_MSG_SIZE, XPNET_MSG_NENTRIES, XPNET_MAX_KTHREADS, XPNET_MAX_IDLE_KTHREADS); - if (ret != xpcSuccess) { + if (ret != xpSuccess) { dev_err(xpnet, "ifconfig up of %s failed on XPC connect, " "ret=%d\n", dev->name, ret); @@ -407,7 +407,7 @@ xpnet_dev_get_stats(struct net_device *dev) * release the skb and then release our pending message structure. */ static void -xpnet_send_completed(enum xpc_retval reason, partid_t partid, int channel, +xpnet_send_completed(enum xp_retval reason, partid_t partid, int channel, void *__qm) { struct xpnet_pending_msg *queued_msg = (struct xpnet_pending_msg *)__qm; @@ -439,7 +439,7 @@ static int xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct xpnet_pending_msg *queued_msg; - enum xpc_retval ret; + enum xp_retval ret; struct xpnet_message *msg; u64 start_addr, end_addr; long dp; @@ -528,7 +528,7 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ret = xpc_allocate(dest_partid, XPC_NET_CHANNEL, XPC_NOWAIT, (void **)&msg); - if (unlikely(ret != xpcSuccess)) + if (unlikely(ret != xpSuccess)) continue; msg->embedded_bytes = embedded_bytes; @@ -557,7 +557,7 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) ret = xpc_send_notify(dest_partid, XPC_NET_CHANNEL, msg, xpnet_send_completed, queued_msg); - if (unlikely(ret != xpcSuccess)) { + if (unlikely(ret != xpSuccess)) { atomic_dec(&queued_msg->use_count); continue; } -- cgit v1.1 From 64d032ba434ad41586460811148f01511e5612f9 Mon Sep 17 00:00:00 2001 From: Dean Nelson Date: Mon, 12 May 2008 14:02:03 -0700 Subject: drivers/misc/sgi-xp: replace partid_t with a short In preparation for supporting greater than 64 partitions replace partid_t by short in drivers/misc/sgi-xp. Signed-off-by: Dean Nelson Acked-by: Robin Holt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/sgi-xp/xp.h | 34 +++++++++++++++++----------------- drivers/misc/sgi-xp/xp_main.c | 30 +++++++++++++++--------------- drivers/misc/sgi-xp/xpc.h | 20 ++++++++++---------- drivers/misc/sgi-xp/xpc_channel.c | 20 ++++++++++---------- drivers/misc/sgi-xp/xpc_main.c | 16 ++++++++-------- drivers/misc/sgi-xp/xpc_partition.c | 10 +++++----- drivers/misc/sgi-xp/xpnet.c | 8 ++++---- 7 files changed, 69 insertions(+), 69 deletions(-) diff --git a/drivers/misc/sgi-xp/xp.h b/drivers/misc/sgi-xp/xp.h index a258fa6..03a87a3 100644 --- a/drivers/misc/sgi-xp/xp.h +++ b/drivers/misc/sgi-xp/xp.h @@ -264,7 +264,7 @@ enum xp_retval { * When a failure reason code is received, one can assume that the channel * is not connected. */ -typedef void (*xpc_channel_func) (enum xp_retval reason, partid_t partid, +typedef void (*xpc_channel_func) (enum xp_retval reason, short partid, int ch_number, void *data, void *key); /* @@ -286,7 +286,7 @@ typedef void (*xpc_channel_func) (enum xp_retval reason, partid_t partid, * * All other reason codes indicate failure. */ -typedef void (*xpc_notify_func) (enum xp_retval reason, partid_t partid, +typedef void (*xpc_notify_func) (enum xp_retval reason, short partid, int ch_number, void *key); /* @@ -322,24 +322,24 @@ struct xpc_registration { struct xpc_interface { void (*connect) (int); void (*disconnect) (int); - enum xp_retval (*allocate) (partid_t, int, u32, void **); - enum xp_retval (*send) (partid_t, int, void *); - enum xp_retval (*send_notify) (partid_t, int, void *, + enum xp_retval (*allocate) (short, int, u32, void **); + enum xp_retval (*send) (short, int, void *); + enum xp_retval (*send_notify) (short, int, void *, xpc_notify_func, void *); - void (*received) (partid_t, int, void *); - enum xp_retval (*partid_to_nasids) (partid_t, void *); + void (*received) (short, int, void *); + enum xp_retval (*partid_to_nasids) (short, void *); }; extern struct xpc_interface xpc_interface; extern void xpc_set_interface(void (*)(int), void (*)(int), - enum xp_retval (*)(partid_t, int, u32, void **), - enum xp_retval (*)(partid_t, int, void *), - enum xp_retval (*)(partid_t, int, void *, + enum xp_retval (*)(short, int, u32, void **), + enum xp_retval (*)(short, int, void *), + enum xp_retval (*)(short, int, void *, xpc_notify_func, void *), - void (*)(partid_t, int, void *), - enum xp_retval (*)(partid_t, void *)); + void (*)(short, int, void *), + enum xp_retval (*)(short, void *)); extern void xpc_clear_interface(void); extern enum xp_retval xpc_connect(int, xpc_channel_func, void *, u16, @@ -347,32 +347,32 @@ extern enum xp_retval xpc_connect(int, xpc_channel_func, void *, u16, extern void xpc_disconnect(int); static inline enum xp_retval -xpc_allocate(partid_t partid, int ch_number, u32 flags, void **payload) +xpc_allocate(short partid, int ch_number, u32 flags, void **payload) { return xpc_interface.allocate(partid, ch_number, flags, payload); } static inline enum xp_retval -xpc_send(partid_t partid, int ch_number, void *payload) +xpc_send(short partid, int ch_number, void *payload) { return xpc_interface.send(partid, ch_number, payload); } static inline enum xp_retval -xpc_send_notify(partid_t partid, int ch_number, void *payload, +xpc_send_notify(short partid, int ch_number, void *payload, xpc_notify_func func, void *key) { return xpc_interface.send_notify(partid, ch_number, payload, func, key); } static inline void -xpc_received(partid_t partid, int ch_number, void *payload) +xpc_received(short partid, int ch_number, void *payload) { return xpc_interface.received(partid, ch_number, payload); } static inline enum xp_retval -xpc_partid_to_nasids(partid_t partid, void *nasids) +xpc_partid_to_nasids(short partid, void *nasids) { return xpc_interface.partid_to_nasids(partid, nasids); } diff --git a/drivers/misc/sgi-xp/xp_main.c b/drivers/misc/sgi-xp/xp_main.c index 0eadaaa..196480b 100644 --- a/drivers/misc/sgi-xp/xp_main.c +++ b/drivers/misc/sgi-xp/xp_main.c @@ -51,12 +51,12 @@ xpc_notloaded(void) struct xpc_interface xpc_interface = { (void (*)(int))xpc_notloaded, (void (*)(int))xpc_notloaded, - (enum xp_retval(*)(partid_t, int, u32, void **))xpc_notloaded, - (enum xp_retval(*)(partid_t, int, void *))xpc_notloaded, - (enum xp_retval(*)(partid_t, int, void *, xpc_notify_func, void *)) + (enum xp_retval(*)(short, int, u32, void **))xpc_notloaded, + (enum xp_retval(*)(short, int, void *))xpc_notloaded, + (enum xp_retval(*)(short, int, void *, xpc_notify_func, void *)) xpc_notloaded, - (void (*)(partid_t, int, void *))xpc_notloaded, - (enum xp_retval(*)(partid_t, void *))xpc_notloaded + (void (*)(short, int, void *))xpc_notloaded, + (enum xp_retval(*)(short, void *))xpc_notloaded }; EXPORT_SYMBOL_GPL(xpc_interface); @@ -66,12 +66,12 @@ EXPORT_SYMBOL_GPL(xpc_interface); void xpc_set_interface(void (*connect) (int), void (*disconnect) (int), - enum xp_retval (*allocate) (partid_t, int, u32, void **), - enum xp_retval (*send) (partid_t, int, void *), - enum xp_retval (*send_notify) (partid_t, int, void *, + enum xp_retval (*allocate) (short, int, u32, void **), + enum xp_retval (*send) (short, int, void *), + enum xp_retval (*send_notify) (short, int, void *, xpc_notify_func, void *), - void (*received) (partid_t, int, void *), - enum xp_retval (*partid_to_nasids) (partid_t, void *)) + void (*received) (short, int, void *), + enum xp_retval (*partid_to_nasids) (short, void *)) { xpc_interface.connect = connect; xpc_interface.disconnect = disconnect; @@ -91,16 +91,16 @@ xpc_clear_interface(void) { xpc_interface.connect = (void (*)(int))xpc_notloaded; xpc_interface.disconnect = (void (*)(int))xpc_notloaded; - xpc_interface.allocate = (enum xp_retval(*)(partid_t, int, u32, + xpc_interface.allocate = (enum xp_retval(*)(short, int, u32, void **))xpc_notloaded; - xpc_interface.send = (enum xp_retval(*)(partid_t, int, void *)) + xpc_interface.send = (enum xp_retval(*)(short, int, void *)) xpc_notloaded; - xpc_interface.send_notify = (enum xp_retval(*)(partid_t, int, void *, + xpc_interface.send_notify = (enum xp_retval(*)(short, int, void *, xpc_notify_func, void *))xpc_notloaded; - xpc_interface.received = (void (*)(partid_t, int, void *)) + xpc_interface.received = (void (*)(short, int, void *)) xpc_notloaded; - xpc_interface.partid_to_nasids = (enum xp_retval(*)(partid_t, void *)) + xpc_interface.partid_to_nasids = (enum xp_retval(*)(short, void *)) xpc_notloaded; } EXPORT_SYMBOL_GPL(xpc_clear_interface); diff --git a/drivers/misc/sgi-xp/xpc.h b/drivers/misc/sgi-xp/xpc.h index 67b179a..11ac267 100644 --- a/drivers/misc/sgi-xp/xpc.h +++ b/drivers/misc/sgi-xp/xpc.h @@ -172,13 +172,13 @@ struct xpc_vars { (_version >= _XPC_VERSION(3, 1)) static inline int -xpc_hb_allowed(partid_t partid, struct xpc_vars *vars) +xpc_hb_allowed(short partid, struct xpc_vars *vars) { return ((vars->heartbeating_to_mask & (1UL << partid)) != 0); } static inline void -xpc_allow_hb(partid_t partid, struct xpc_vars *vars) +xpc_allow_hb(short partid, struct xpc_vars *vars) { u64 old_mask, new_mask; @@ -190,7 +190,7 @@ xpc_allow_hb(partid_t partid, struct xpc_vars *vars) } static inline void -xpc_disallow_hb(partid_t partid, struct xpc_vars *vars) +xpc_disallow_hb(short partid, struct xpc_vars *vars) { u64 old_mask, new_mask; @@ -408,7 +408,7 @@ struct xpc_notify { * messages. */ struct xpc_channel { - partid_t partid; /* ID of remote partition connected */ + short partid; /* ID of remote partition connected */ spinlock_t lock; /* lock for updating this structure */ u32 flags; /* general flags */ @@ -615,7 +615,7 @@ struct xpc_partition { /* interval in seconds to print 'waiting disengagement' messages */ #define XPC_DISENGAGE_PRINTMSG_INTERVAL 10 -#define XPC_PARTID(_p) ((partid_t) ((_p) - &xpc_partitions[0])) +#define XPC_PARTID(_p) ((short)((_p) - &xpc_partitions[0])) /* found in xp_main.c */ extern struct xpc_registration xpc_registrations[]; @@ -652,16 +652,16 @@ extern void xpc_discovery(void); extern void xpc_check_remote_hb(void); extern void xpc_deactivate_partition(const int, struct xpc_partition *, enum xp_retval); -extern enum xp_retval xpc_initiate_partid_to_nasids(partid_t, void *); +extern enum xp_retval xpc_initiate_partid_to_nasids(short, void *); /* found in xpc_channel.c */ extern void xpc_initiate_connect(int); extern void xpc_initiate_disconnect(int); -extern enum xp_retval xpc_initiate_allocate(partid_t, int, u32, void **); -extern enum xp_retval xpc_initiate_send(partid_t, int, void *); -extern enum xp_retval xpc_initiate_send_notify(partid_t, int, void *, +extern enum xp_retval xpc_initiate_allocate(short, int, u32, void **); +extern enum xp_retval xpc_initiate_send(short, int, void *); +extern enum xp_retval xpc_initiate_send_notify(short, int, void *, xpc_notify_func, void *); -extern void xpc_initiate_received(partid_t, int, void *); +extern void xpc_initiate_received(short, int, void *); extern enum xp_retval xpc_setup_infrastructure(struct xpc_partition *); extern enum xp_retval xpc_pull_remote_vars_part(struct xpc_partition *); extern void xpc_process_channel_activity(struct xpc_partition *); diff --git a/drivers/misc/sgi-xp/xpc_channel.c b/drivers/misc/sgi-xp/xpc_channel.c index 74ec506..9c90c2d 100644 --- a/drivers/misc/sgi-xp/xpc_channel.c +++ b/drivers/misc/sgi-xp/xpc_channel.c @@ -53,7 +53,7 @@ xpc_kzalloc_cacheline_aligned(size_t size, gfp_t flags, void **base) * Set up the initial values for the XPartition Communication channels. */ static void -xpc_initialize_channels(struct xpc_partition *part, partid_t partid) +xpc_initialize_channels(struct xpc_partition *part, short partid) { int ch_number; struct xpc_channel *ch; @@ -95,7 +95,7 @@ xpc_setup_infrastructure(struct xpc_partition *part) { int ret, cpuid; struct timer_list *timer; - partid_t partid = XPC_PARTID(part); + short partid = XPC_PARTID(part); /* * Zero out MOST of the entry for this partition. Only the fields @@ -290,7 +290,7 @@ xpc_pull_remote_vars_part(struct xpc_partition *part) (struct xpc_vars_part *)L1_CACHE_ALIGN((u64)buffer); struct xpc_vars_part *pulled_entry; u64 remote_entry_cacheline_pa, remote_entry_pa; - partid_t partid = XPC_PARTID(part); + short partid = XPC_PARTID(part); enum xp_retval ret; /* pull the cacheline that contains the variables we're interested in */ @@ -1375,7 +1375,7 @@ xpc_partition_going_down(struct xpc_partition *part, enum xp_retval reason) void xpc_teardown_infrastructure(struct xpc_partition *part) { - partid_t partid = XPC_PARTID(part); + short partid = XPC_PARTID(part); /* * We start off by making this partition inaccessible to local @@ -1428,7 +1428,7 @@ xpc_teardown_infrastructure(struct xpc_partition *part) void xpc_initiate_connect(int ch_number) { - partid_t partid; + short partid; struct xpc_partition *part; struct xpc_channel *ch; @@ -1484,7 +1484,7 @@ void xpc_initiate_disconnect(int ch_number) { unsigned long irq_flags; - partid_t partid; + short partid; struct xpc_partition *part; struct xpc_channel *ch; @@ -1728,7 +1728,7 @@ xpc_allocate_msg(struct xpc_channel *ch, u32 flags, * return) in which the user-defined message is constructed. */ enum xp_retval -xpc_initiate_allocate(partid_t partid, int ch_number, u32 flags, void **payload) +xpc_initiate_allocate(short partid, int ch_number, u32 flags, void **payload) { struct xpc_partition *part = &xpc_partitions[partid]; enum xp_retval ret = xpUnknownReason; @@ -1909,7 +1909,7 @@ xpc_send_msg(struct xpc_channel *ch, struct xpc_msg *msg, u8 notify_type, * xpc_initiate_allocate(). */ enum xp_retval -xpc_initiate_send(partid_t partid, int ch_number, void *payload) +xpc_initiate_send(short partid, int ch_number, void *payload) { struct xpc_partition *part = &xpc_partitions[partid]; struct xpc_msg *msg = XPC_MSG_ADDRESS(payload); @@ -1958,7 +1958,7 @@ xpc_initiate_send(partid_t partid, int ch_number, void *payload) * key - user-defined key to be passed to the function when it's called. */ enum xp_retval -xpc_initiate_send_notify(partid_t partid, int ch_number, void *payload, +xpc_initiate_send_notify(short partid, int ch_number, void *payload, xpc_notify_func func, void *key) { struct xpc_partition *part = &xpc_partitions[partid]; @@ -2203,7 +2203,7 @@ xpc_acknowledge_msgs(struct xpc_channel *ch, s64 initial_get, u8 msg_flags) * xpc_initiate_allocate(). */ void -xpc_initiate_received(partid_t partid, int ch_number, void *payload) +xpc_initiate_received(short partid, int ch_number, void *payload) { struct xpc_partition *part = &xpc_partitions[partid]; struct xpc_channel *ch; diff --git a/drivers/misc/sgi-xp/xpc_main.c b/drivers/misc/sgi-xp/xpc_main.c index 2765b42..08256ed 100644 --- a/drivers/misc/sgi-xp/xpc_main.c +++ b/drivers/misc/sgi-xp/xpc_main.c @@ -429,7 +429,7 @@ xpc_partition_up(struct xpc_partition *part) static int xpc_activating(void *__partid) { - partid_t partid = (u64)__partid; + short partid = (u64)__partid; struct xpc_partition *part = &xpc_partitions[partid]; unsigned long irq_flags; @@ -499,7 +499,7 @@ xpc_activating(void *__partid) void xpc_activate_partition(struct xpc_partition *part) { - partid_t partid = XPC_PARTID(part); + short partid = XPC_PARTID(part); unsigned long irq_flags; struct task_struct *kthread; @@ -541,7 +541,7 @@ xpc_activate_partition(struct xpc_partition *part) irqreturn_t xpc_notify_IRQ_handler(int irq, void *dev_id) { - partid_t partid = (partid_t) (u64)dev_id; + short partid = (short)(u64)dev_id; struct xpc_partition *part = &xpc_partitions[partid]; DBUG_ON(partid <= 0 || partid >= XP_MAX_PARTITIONS); @@ -643,7 +643,7 @@ xpc_kthread_waitmsgs(struct xpc_partition *part, struct xpc_channel *ch) static int xpc_kthread_start(void *args) { - partid_t partid = XPC_UNPACK_ARG1(args); + short partid = XPC_UNPACK_ARG1(args); u16 ch_number = XPC_UNPACK_ARG2(args); struct xpc_partition *part = &xpc_partitions[partid]; struct xpc_channel *ch; @@ -809,7 +809,7 @@ void xpc_disconnect_wait(int ch_number) { unsigned long irq_flags; - partid_t partid; + short partid; struct xpc_partition *part; struct xpc_channel *ch; int wakeup_channel_mgr; @@ -859,7 +859,7 @@ xpc_disconnect_wait(int ch_number) static void xpc_do_exit(enum xp_retval reason) { - partid_t partid; + short partid; int active_part_count, printed_waiting_msg = 0; struct xpc_partition *part; unsigned long printmsg_time, disengage_request_timeout = 0; @@ -1008,7 +1008,7 @@ static void xpc_die_disengage(void) { struct xpc_partition *part; - partid_t partid; + short partid; unsigned long engaged; long time, printmsg_time, disengage_request_timeout; @@ -1124,7 +1124,7 @@ int __init xpc_init(void) { int ret; - partid_t partid; + short partid; struct xpc_partition *part; struct task_struct *kthread; size_t buf_size; diff --git a/drivers/misc/sgi-xp/xpc_partition.c b/drivers/misc/sgi-xp/xpc_partition.c index d9b462e..7dd4b58 100644 --- a/drivers/misc/sgi-xp/xpc_partition.c +++ b/drivers/misc/sgi-xp/xpc_partition.c @@ -403,7 +403,7 @@ xpc_check_remote_hb(void) { struct xpc_vars *remote_vars; struct xpc_partition *part; - partid_t partid; + short partid; bte_result_t bres; remote_vars = (struct xpc_vars *)xpc_remote_copy_buffer; @@ -604,7 +604,7 @@ xpc_identify_act_IRQ_req(int nasid) int reactivate = 0; int stamp_diff; struct timespec remote_rp_stamp = { 0, 0 }; - partid_t partid; + short partid; struct xpc_partition *part; enum xp_retval ret; @@ -825,7 +825,7 @@ xpc_identify_act_IRQ_sender(void) int xpc_partition_disengaged(struct xpc_partition *part) { - partid_t partid = XPC_PARTID(part); + short partid = XPC_PARTID(part); int disengaged; disengaged = (xpc_partition_engaged(1UL << partid) == 0); @@ -982,7 +982,7 @@ xpc_discovery(void) int max_regions; int nasid; struct xpc_rsvd_page *rp; - partid_t partid; + short partid; struct xpc_partition *part; u64 *discovered_nasids; enum xp_retval ret; @@ -1152,7 +1152,7 @@ xpc_discovery(void) * remote partition's reserved page. */ enum xp_retval -xpc_initiate_partid_to_nasids(partid_t partid, void *nasid_mask) +xpc_initiate_partid_to_nasids(short partid, void *nasid_mask) { struct xpc_partition *part; u64 part_nasid_pa; diff --git a/drivers/misc/sgi-xp/xpnet.c b/drivers/misc/sgi-xp/xpnet.c index 38df166..822dc8e 100644 --- a/drivers/misc/sgi-xp/xpnet.c +++ b/drivers/misc/sgi-xp/xpnet.c @@ -166,7 +166,7 @@ struct device *xpnet = &xpnet_dbg_subname; * Packet was recevied by XPC and forwarded to us. */ static void -xpnet_receive(partid_t partid, int channel, struct xpnet_message *msg) +xpnet_receive(short partid, int channel, struct xpnet_message *msg) { struct sk_buff *skb; bte_result_t bret; @@ -282,7 +282,7 @@ xpnet_receive(partid_t partid, int channel, struct xpnet_message *msg) * state or message reception on a connection. */ static void -xpnet_connection_activity(enum xp_retval reason, partid_t partid, int channel, +xpnet_connection_activity(enum xp_retval reason, short partid, int channel, void *data, void *key) { long bp; @@ -407,7 +407,7 @@ xpnet_dev_get_stats(struct net_device *dev) * release the skb and then release our pending message structure. */ static void -xpnet_send_completed(enum xp_retval reason, partid_t partid, int channel, +xpnet_send_completed(enum xp_retval reason, short partid, int channel, void *__qm) { struct xpnet_pending_msg *queued_msg = (struct xpnet_pending_msg *)__qm; @@ -444,7 +444,7 @@ xpnet_dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) u64 start_addr, end_addr; long dp; u8 second_mac_octet; - partid_t dest_partid; + short dest_partid; struct xpnet_dev_private *priv; u16 embedded_bytes; -- cgit v1.1 From 8dc4e37362a5dc910d704d52ac6542bfd49ddc2f Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 12 May 2008 14:02:04 -0700 Subject: ecryptfs: clean up (un)lock_parent dget(dentry->d_parent) --> dget_parent(dentry) unlock_parent() is racy and unnecessary. Replace single caller with unlock_dir(). There are several other suspect uses of ->d_parent in ecryptfs... Signed-off-by: Miklos Szeredi Cc: Michael Halcrow Cc: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ecryptfs/inode.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/fs/ecryptfs/inode.c b/fs/ecryptfs/inode.c index 0a13973..c92cc1c 100644 --- a/fs/ecryptfs/inode.c +++ b/fs/ecryptfs/inode.c @@ -37,17 +37,11 @@ static struct dentry *lock_parent(struct dentry *dentry) { struct dentry *dir; - dir = dget(dentry->d_parent); + dir = dget_parent(dentry); mutex_lock_nested(&(dir->d_inode->i_mutex), I_MUTEX_PARENT); return dir; } -static void unlock_parent(struct dentry *dentry) -{ - mutex_unlock(&(dentry->d_parent->d_inode->i_mutex)); - dput(dentry->d_parent); -} - static void unlock_dir(struct dentry *dir) { mutex_unlock(&dir->d_inode->i_mutex); @@ -426,8 +420,9 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry) int rc = 0; struct dentry *lower_dentry = ecryptfs_dentry_to_lower(dentry); struct inode *lower_dir_inode = ecryptfs_inode_to_lower(dir); + struct dentry *lower_dir_dentry; - lock_parent(lower_dentry); + lower_dir_dentry = lock_parent(lower_dentry); rc = vfs_unlink(lower_dir_inode, lower_dentry); if (rc) { printk(KERN_ERR "Error in vfs_unlink; rc = [%d]\n", rc); @@ -439,7 +434,7 @@ static int ecryptfs_unlink(struct inode *dir, struct dentry *dentry) dentry->d_inode->i_ctime = dir->i_ctime; d_drop(dentry); out_unlock: - unlock_parent(lower_dentry); + unlock_dir(lower_dir_dentry); return rc; } -- cgit v1.1 From 78f508ab07954d12896097ac07ab2fab443c7ca2 Mon Sep 17 00:00:00 2001 From: Sebastian Siewior Date: Mon, 12 May 2008 14:02:05 -0700 Subject: m68knommu: ColdFire add support for kernel preemption (missing chunk) As the subject says this patch adds the support for kernel preemption on m68knommu Coldfire. I thing the same changes could be applied to 68360 & 68328 but since I don't have the HW, I don't touch it. Kconfig enables the preemption item only on coldfire. This is a missing chunk from Sebastian's original patch that I lost from the first submission. Signed-off-by: Sebastian Siewior Signed-off-by: Greg Ungerer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/m68knommu/Kconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/m68knommu/Kconfig b/arch/m68knommu/Kconfig index 07eb4c4..8e84415 100644 --- a/arch/m68knommu/Kconfig +++ b/arch/m68knommu/Kconfig @@ -671,6 +671,9 @@ config ROMKERNEL endchoice +if COLDFIRE +source "kernel/Kconfig.preempt" +endif source "mm/Kconfig" endmenu -- cgit v1.1 From b5be11329f8cb2cc1a4c3b33b6b8d096c6012895 Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Mon, 12 May 2008 14:02:06 -0700 Subject: make vmstat cpu-unplug safe When accessing cpu_online_map, we should prevent dynamic changing of cpu_online_map by get_online_cpus(). Unfortunately, all_vm_events() doesn't do that. Signed-off-by: KOSAKI Motohiro Acked-by: Christoph Lameter Cc: Gautham R Shenoy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/vmstat.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/vmstat.c b/mm/vmstat.c index 1a32130..db9eabb 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c @@ -41,7 +41,9 @@ static void sum_vm_events(unsigned long *ret, cpumask_t *cpumask) */ void all_vm_events(unsigned long *ret) { + get_online_cpus(); sum_vm_events(ret, &cpu_online_map); + put_online_cpus(); } EXPORT_SYMBOL_GPL(all_vm_events); -- cgit v1.1 From bb45d64224e5cafe8c8e0d18a20da998e5a7dc93 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 12 May 2008 14:02:06 -0700 Subject: ufs: remove unneeded ufs_put_inode prototype Signed-off-by: Christoph Hellwig Acked-by: Evgeniy Dushistov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ufs/ufs.h | 1 - 1 file changed, 1 deletion(-) diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index 244a1aa..11c0351 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h @@ -107,7 +107,6 @@ extern struct inode * ufs_new_inode (struct inode *, int); /* inode.c */ extern struct inode *ufs_iget(struct super_block *, unsigned long); -extern void ufs_put_inode (struct inode *); extern int ufs_write_inode (struct inode *, int); extern int ufs_sync_inode (struct inode *); extern void ufs_delete_inode (struct inode *); -- cgit v1.1 From 9377abd026bf9bde7db90dac09170034bf6d1cbf Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 12 May 2008 14:02:08 -0700 Subject: quota: don't call sync_fs() from vfs_quota_off() when there's no quota turn off Sometimes, vfs_quota_off() is called on a partially set up super block (for example when fill_super() fails for some reason). In such cases we cannot call ->sync_fs() because it can Oops because of not properly filled in super block. So in case we find there's not quota to turn off, we just skip everything and return which fixes the above problem. [akpm@linux-foundation.org: fxi tpyo] Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/dquot.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/fs/dquot.c b/fs/dquot.c index dfba162..5ac77da 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -1491,6 +1491,16 @@ int vfs_quota_off(struct super_block *sb, int type, int remount) /* We need to serialize quota_off() for device */ mutex_lock(&dqopt->dqonoff_mutex); + + /* + * Skip everything if there's nothing to do. We have to do this because + * sometimes we are called when fill_super() failed and calling + * sync_fs() in such cases does no good. + */ + if (!sb_any_quota_enabled(sb) && !sb_any_quota_suspended(sb)) { + mutex_unlock(&dqopt->dqonoff_mutex); + return 0; + } for (cnt = 0; cnt < MAXQUOTAS; cnt++) { toputinode[cnt] = NULL; if (type != -1 && cnt != type) -- cgit v1.1 From 55654be9e11461484141d8dff0715efa0d7a945a Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Mon, 12 May 2008 14:02:08 -0700 Subject: mmc: make one-bit signed bitfields unsigned Otherwise it can only take the values 0/-1 which doesn't seem to have been intended. drivers/mmc/host/sdhci.h:190:20: error: dubious one-bit signed bitfield Signed-off-by: Harvey Harrison Acked-by: Pierre Ossman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mmc/host/sdhci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 7fb02e1..299118d 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h @@ -187,7 +187,7 @@ struct sdhci_host { struct mmc_request *mrq; /* Current request */ struct mmc_command *cmd; /* Current command */ struct mmc_data *data; /* Current data request */ - int data_early:1; /* Data finished before cmd */ + unsigned int data_early:1; /* Data finished before cmd */ struct scatterlist *cur_sg; /* We're working on this */ int num_sg; /* Entries left */ -- cgit v1.1 From 6fb488239cd8750cc818197d6c346409c0e8d330 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Mon, 12 May 2008 14:02:09 -0700 Subject: tridentfb: remove misplaced enable_mmio() Remove redundant enable_mmio() call as the mmio mode is enabled in the probe function earlier. Signed-off-by: Krzysztof Helt Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/tridentfb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index bd54cd0..982eeee 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c @@ -905,7 +905,6 @@ static int tridentfb_set_par(struct fb_info *info) vblankstart = var->yres; vblankend = vtotal + 2; - enable_mmio(); crtc_unlock(); write3CE(CyberControl, 8); -- cgit v1.1 From 3f275ea3086054205795972b8e87f2046fd3de98 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Mon, 12 May 2008 14:02:11 -0700 Subject: tridentfb: improve clock setting accuracy Improve clock calculation precision (to kHz from MHz) and removes parameter field vclk from the tridentfb_par structure. Signed-off-by: Krzysztof Helt Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/tridentfb.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index 982eeee..beefab2 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c @@ -27,7 +27,6 @@ #define VERSION "0.7.8-NEWAPI" struct tridentfb_par { - int vclk; /* in MHz */ void __iomem *io_virt; /* iospace virtual memory address */ }; @@ -669,27 +668,26 @@ static void set_screen_start(int base) (read3X4(CRTHiOrd) & 0xF8) | ((base & 0xE0000) >> 17)); } -/* Use 20.12 fixed-point for NTSC value and frequency calculation */ -#define calc_freq(n, m, k) ( ((unsigned long)0xE517 * (n + 8) / ((m + 2) * (1 << k))) >> 12 ) - /* Set dotclock frequency */ -static void set_vclk(int freq) +static void set_vclk(unsigned long freq) { int m, n, k; - int f, fi, d, di; + unsigned long f, fi, d, di; unsigned char lo = 0, hi = 0; - d = 20; + d = 20000; for (k = 2; k >= 0; k--) for (m = 0; m < 63; m++) for (n = 0; n < 128; n++) { - fi = calc_freq(n, m, k); + fi = ((14318l * (n + 8)) / (m + 2)) >> k; if ((di = abs(fi - freq)) < d) { d = di; f = fi; lo = n; hi = (k << 6) | m; } + if (fi > freq) + break; } if (chip3D) { write3C4(ClockHigh, hi); @@ -888,6 +886,8 @@ static int tridentfb_set_par(struct fb_info *info) struct fb_var_screeninfo *var = &info->var; int bpp = var->bits_per_pixel; unsigned char tmp; + unsigned long vclk; + debug("enter\n"); hdispend = var->xres / 8 - 1; hsyncstart = (var->xres + var->right_margin) / 8; @@ -1014,11 +1014,11 @@ static int tridentfb_set_par(struct fb_info *info) write3X4(Performance, 0x92); write3X4(PCIReg, 0x07); /* MMIO & PCI read and write burst enable */ - /* convert from picoseconds to MHz */ - par->vclk = 1000000 / info->var.pixclock; + /* convert from picoseconds to kHz */ + vclk = PICOS2KHZ(info->var.pixclock); if (bpp == 32) - par->vclk *= 2; - set_vclk(par->vclk); + vclk *= 2; + set_vclk(vclk); write3C4(0, 3); write3C4(1, 1); /* set char clock 8 dots wide */ -- cgit v1.1 From c8894419acf5e56851de9741c5047bebd78acd1f Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 12 May 2008 14:02:12 -0700 Subject: md: fix raid5 'repair' operations commit bd2ab67030e9116f1e4aae1289220255412b37fd "md: close a livelock window in handle_parity_checks5" introduced a bug in handling 'repair' operations. After a repair operation completes we clear the state bits tracking this operation. However, they are cleared too early and this results in the code deciding to re-run the parity check operation. Since we have done the repair in memory the second check does not find a mismatch and thus does not do a writeback. Test results: $ echo repair > /sys/block/md0/md/sync_action $ cat /sys/block/md0/md/mismatch_cnt 51072 $ echo repair > /sys/block/md0/md/sync_action $ cat /sys/block/md0/md/mismatch_cnt 0 (also fix incorrect indentation) Cc: Tested-by: George Spelvin Acked-by: NeilBrown Signed-off-by: Dan Williams Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 087eee0..ee0ea91 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -2369,8 +2369,8 @@ static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh, /* complete a check operation */ if (test_and_clear_bit(STRIPE_OP_CHECK, &sh->ops.complete)) { - clear_bit(STRIPE_OP_CHECK, &sh->ops.ack); - clear_bit(STRIPE_OP_CHECK, &sh->ops.pending); + clear_bit(STRIPE_OP_CHECK, &sh->ops.ack); + clear_bit(STRIPE_OP_CHECK, &sh->ops.pending); if (s->failed == 0) { if (sh->ops.zero_sum_result == 0) /* parity is correct (on disc, @@ -2400,16 +2400,6 @@ static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh, canceled_check = 1; /* STRIPE_INSYNC is not set */ } - /* check if we can clear a parity disk reconstruct */ - if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) && - test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) { - - clear_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending); - clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete); - clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack); - clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending); - } - /* start a new check operation if there are no failures, the stripe is * not insync, and a repair is not in flight */ @@ -2424,6 +2414,17 @@ static void handle_parity_checks5(raid5_conf_t *conf, struct stripe_head *sh, } } + /* check if we can clear a parity disk reconstruct */ + if (test_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete) && + test_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending)) { + + clear_bit(STRIPE_OP_MOD_REPAIR_PD, &sh->ops.pending); + clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.complete); + clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.ack); + clear_bit(STRIPE_OP_COMPUTE_BLK, &sh->ops.pending); + } + + /* Wait for check parity and compute block operations to complete * before write-back. If a failure occurred while the check operation * was in flight we need to cycle this stripe through handle_stripe -- cgit v1.1 From 289f8e27ed435dcbefad132def06f4e84351e94f Mon Sep 17 00:00:00 2001 From: "Serge E. Hallyn" Date: Mon, 12 May 2008 14:02:13 -0700 Subject: capabilities: add bounding set to /proc/self/status There is currently no way to query the bounding set of another task. As there appears to be no security reason not to, and as Michael Kerrisk points out the following valid reasons to do so exist: * consistency (I can see all of the other per-thread/process sets in /proc/.../status) * debugging -- I could imagine that it would make the job of debugging an application that uses capabilities a little simpler. this patch adds the bounding set to /proc/self/status right after the effective set. Signed-off-by: Serge E. Hallyn Acked-by: Michael Kerrisk Acked-by: Andrew G. Morgan Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/proc/array.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/proc/array.c b/fs/proc/array.c index dca997a..9e3b8c3 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -298,6 +298,7 @@ static inline void task_cap(struct seq_file *m, struct task_struct *p) render_cap_t(m, "CapInh:\t", &p->cap_inheritable); render_cap_t(m, "CapPrm:\t", &p->cap_permitted); render_cap_t(m, "CapEff:\t", &p->cap_effective); + render_cap_t(m, "CapBnd:\t", &p->cap_bset); } static inline void task_context_switch_counts(struct seq_file *m, -- cgit v1.1 From 241937b863c8a3ef10511712f53285f41ab05308 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Mon, 12 May 2008 14:02:13 -0700 Subject: adt7473: minor documentation update Add a sentence about when fan speed increases to maximum. Signed-off-by: Darrick J. Wong Acked-by: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/hwmon/adt7473 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/hwmon/adt7473 b/Documentation/hwmon/adt7473 index 22d8b19..2126de3 100644 --- a/Documentation/hwmon/adt7473 +++ b/Documentation/hwmon/adt7473 @@ -69,7 +69,8 @@ point2: Set the pwm speed at a higher temperature bound. The ADT7473 will scale the pwm between the lower and higher pwm speed when the temperature is between the two temperature boundaries. PWM values range -from 0 (off) to 255 (full speed). +from 0 (off) to 255 (full speed). Fan speed will be set to maximum when the +temperature sensor associated with the PWM control exceeds temp#_max. Notes ----- -- cgit v1.1 From 5aecd559871d23a3cc297e544c9d63f0b8441cf4 Mon Sep 17 00:00:00 2001 From: Denis Cheng Date: Mon, 12 May 2008 14:02:14 -0700 Subject: mm/pdflush.c: merge the same code in two path Signed-off-by: Denis Cheng Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/pdflush.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mm/pdflush.c b/mm/pdflush.c index 1c96cfc..9d834aa 100644 --- a/mm/pdflush.c +++ b/mm/pdflush.c @@ -207,7 +207,6 @@ int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0) spin_lock_irqsave(&pdflush_lock, flags); if (list_empty(&pdflush_list)) { - spin_unlock_irqrestore(&pdflush_lock, flags); ret = -1; } else { struct pdflush_work *pdf; @@ -219,8 +218,9 @@ int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0) pdf->fn = fn; pdf->arg0 = arg0; wake_up_process(pdf->who); - spin_unlock_irqrestore(&pdflush_lock, flags); } + spin_unlock_irqrestore(&pdflush_lock, flags); + return ret; } -- cgit v1.1 From 7a6278e5e4bce72ace681ae3cf48209fb63a5420 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 12 May 2008 14:02:16 -0700 Subject: drivers/video/pnx4008: eliminate double free The function framebuffer_release just calls kfree, so calling kfree subsequently on the same argument represents a double free. The comments with the definition of framebuffer_release in drivers/video/fbsysfs.c suggest that a more elaborate definition of this function is planned, such that the splitting up of framebuffer_release and kfree as done in the second instance might someday make sense, but it does not make sense now. This was found using the following semantic match. (http://www.emn.fr/x-info/coccinelle/) // @@ expression E; @@ * kfree(E); ... * framebuffer_release(E); @@ expression E; @@ * framebuffer_release(E); ... * kfree(E); // Signed-off-by: Julia Lawall Cc: Vitaly Wool Cc: Krzysztof Helt Cc: Grigory Tolstolytkin Cc: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/pnx4008/pnxrgbfb.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/video/pnx4008/pnxrgbfb.c b/drivers/video/pnx4008/pnxrgbfb.c index 685761a..4db6b48 100644 --- a/drivers/video/pnx4008/pnxrgbfb.c +++ b/drivers/video/pnx4008/pnxrgbfb.c @@ -100,7 +100,6 @@ static int rgbfb_remove(struct platform_device *pdev) fb_dealloc_cmap(&info->cmap); framebuffer_release(info); platform_set_drvdata(pdev, NULL); - kfree(info); } pnx4008_free_dum_channel(channel_owned, pdev->id); @@ -168,23 +167,21 @@ static int __devinit rgbfb_probe(struct platform_device *pdev) ret = fb_alloc_cmap(&info->cmap, 256, 0); if (ret < 0) - goto err2; + goto err1; ret = register_framebuffer(info); if (ret < 0) - goto err3; + goto err2; platform_set_drvdata(pdev, info); return 0; -err3: - fb_dealloc_cmap(&info->cmap); err2: - framebuffer_release(info); + fb_dealloc_cmap(&info->cmap); err1: pnx4008_free_dum_channel(channel_owned, pdev->id); err0: - kfree(info); + framebuffer_release(info); err: return ret; } -- cgit v1.1 From 460817b9d45be7b2a50e1e24eb91b4aa0c435a09 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Mon, 12 May 2008 14:02:17 -0700 Subject: mn10300: replace deprecated "TOPDIR" with newer "srctree" This would appear to be the last reference to TOPDIR in the entire tree, after which i'm guessing that variable can be dropped. Signed-off-by: Robert P. J. Day Acked-by: David Howells Cc: Sam Ravnborg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/mn10300/boot/install.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/mn10300/boot/install.sh b/arch/mn10300/boot/install.sh index 072951c..abba309 100644 --- a/arch/mn10300/boot/install.sh +++ b/arch/mn10300/boot/install.sh @@ -26,42 +26,42 @@ rm -fr $4/../usr/include/linux $4/../usr/include/asm install -c -m 0755 $2 $4/vmlinuz install -c -m 0755 $5 $4/boot.rom install -c -m 0755 -d $4/../usr/include/linux -cd $TOPDIR/include/linux +cd ${srctree}/include/linux for i in `find . -maxdepth 1 -name '*.h' -print`; do install -c -m 0644 $i $4/../usr/include/linux done install -c -m 0755 -d $4/../usr/include/linux/byteorder -cd $TOPDIR/include/linux/byteorder +cd ${srctree}/include/linux/byteorder for i in `find . -name '*.h' -print`; do install -c -m 0644 $i $4/../usr/include/linux/byteorder done install -c -m 0755 -d $4/../usr/include/linux/lockd -cd $TOPDIR/include/linux/lockd +cd ${srctree}/include/linux/lockd for i in `find . -name '*.h' -print`; do install -c -m 0644 $i $4/../usr/include/linux/lockd done install -c -m 0755 -d $4/../usr/include/linux/netfilter_ipv4 -cd $TOPDIR/include/linux/netfilter_ipv4 +cd ${srctree}/include/linux/netfilter_ipv4 for i in `find . -name '*.h' -print`; do install -c -m 0644 $i $4/../usr/include/linux/netfilter_ipv4 done install -c -m 0755 -d $4/../usr/include/linux/nfsd -cd $TOPDIR/include/linux/nfsd +cd ${srctree}/include/linux/nfsd for i in `find . -name '*.h' -print`; do install -c -m 0644 $i $4/../usr/include/linux/nfsd/$i done install -c -m 0755 -d $4/../usr/include/linux/raid -cd $TOPDIR/include/linux/raid +cd ${srctree}/include/linux/raid for i in `find . -name '*.h' -print`; do install -c -m 0644 $i $4/../usr/include/linux/raid done install -c -m 0755 -d $4/../usr/include/linux/sunrpc -cd $TOPDIR/include/linux/sunrpc +cd ${srctree}/include/linux/sunrpc for i in `find . -name '*.h' -print`; do install -c -m 0644 $i $4/../usr/include/linux/sunrpc done install -c -m 0755 -d $4/../usr/include/asm -cd $TOPDIR/include/asm +cd ${srctree}/include/asm for i in `find . -name '*.h' -print`; do install -c -m 0644 $i $4/../usr/include/asm done -- cgit v1.1 From f2a5f24a279a21229e8c42198e21e2c8ce289129 Mon Sep 17 00:00:00 2001 From: Bjorn Helgaas Date: Mon, 12 May 2008 14:02:18 -0700 Subject: PNP: set IRQ index in sysfs "set irq" interface We have to set the ISAPNP register index when setting an IRQ via the sysfs interface. We already do it for IO, MEM, and DMA resources; I just missed the IRQ one. Signed-off-by: Bjorn Helgaas Cc: Len Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pnp/interface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pnp/interface.c b/drivers/pnp/interface.c index 5d9301de..5695a79 100644 --- a/drivers/pnp/interface.c +++ b/drivers/pnp/interface.c @@ -424,7 +424,7 @@ pnp_set_current_resources(struct device *dmdev, struct device_attribute *attr, start = simple_strtoul(buf, &buf, 0); pnp_res = pnp_add_irq_resource(dev, start, 0); if (pnp_res) - nirq++; + pnp_res->index = nirq++; continue; } if (!strnicmp(buf, "dma", 3)) { -- cgit v1.1 From 4413a0f637df4e59b934909ac388a21cfdd90e69 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 12 May 2008 14:02:19 -0700 Subject: parisc: fix DISCONTIGMEM compile breakage PA-RISC to aid debugging prints out the zonelists setup by the system. A bad call to node_zonelist() breaks at compile-time. This patch fixes it. Signed-off-by: Mel Gorman Cc: Christoph Lameter Cc: Lee Schermerhorn Cc: Kyle McMartin Cc: Grant Grundler Cc: James Bottomley Cc: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/parisc/mm/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 1f01284..b0ed709 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -606,7 +606,7 @@ void show_mem(void) int i, j; for (i = 0; i < npmem_ranges; i++) { - zl = node_zonelist(i); + zl = node_zonelist(i, 0); for (j = 0; j < MAX_NR_ZONES; j++) { struct zoneref *z; struct zone *zone; -- cgit v1.1 From 706322496b3a58af3cf258db2b553d6933656eef Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Mon, 12 May 2008 14:02:21 -0700 Subject: Fix hfsplus oops on image without extents Fix an oops with a corrupted hfs+ image. See http://bugzilla.kernel.org/show_bug.cgi?id=10548 for details. Problem is that we call hfs_btree_open() from hfsplus_fill_super() to set HFSPLUS_SB(sb).[ext_tree|cat_tree] Both trees are still NULL at this moment. If hfs_btree_open() fails for any reason it calls iput() on the page, which gets to hfsplus_releasepage() which tries to access HFSPLUS_SB(sb).* which is still NULL and oopses while dereferencing it. [akpm@linux-foundation.org: build fix] Signed-off-by: Eric Sesterhenn Cc: Roman Zippel Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/hfsplus/inode.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index d53b2af..67e1c8b 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -65,6 +65,8 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask) BUG(); return 0; } + if (!tree) + return 0; if (tree->node_size >= PAGE_CACHE_SIZE) { nidx = page->index >> (tree->node_size_shift - PAGE_CACHE_SHIFT); spin_lock(&tree->hash_lock); -- cgit v1.1 From 67d7671036e6cae24ded112e079926d55ffe9580 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Mon, 12 May 2008 14:02:22 -0700 Subject: Update Geode mailing list in MAINTAINERS Update the Geode list location in the MAINTAINERS file. Signed-off-by: Jordan Crouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index f5583dc..b18242f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -367,12 +367,12 @@ S: Maintained for 2.4; PCI support for 2.6. AMD GEODE CS5536 USB DEVICE CONTROLLER DRIVER P: Thomas Dahlmann M: thomas.dahlmann@amd.com -L: info-linux@geode.amd.com (subscribers-only) +L: linux-geode@lists.infradead.org (moderated for non-subscribers) S: Supported AMD GEODE PROCESSOR/CHIPSET SUPPORT P: Jordan Crouse -L: info-linux@geode.amd.com (subscribers-only) +L: linux-geode@lists.infradead.org (moderated for non-subscribers) W: http://www.amd.com/us-en/ConnectivitySolutions/TechnicalResources/0,,50_2334_2452_11363,00.html S: Supported -- cgit v1.1 From e662e1cfd434aa234b72fbc781f1d70211cb785b Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 12 May 2008 14:02:22 -0700 Subject: init: don't lose initcall return values There is an ability to lose an initcall return value if it happened with irq disabled or imbalanced preemption (and if we debug initcall). Signed-off-by: Cyrill Gorcunov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/main.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/init/main.c b/init/main.c index ddada7a..f406fef 100644 --- a/init/main.c +++ b/init/main.c @@ -702,7 +702,6 @@ static void __init do_initcalls(void) for (call = __initcall_start; call < __initcall_end; call++) { ktime_t t0, t1, delta; - char *msg = NULL; char msgbuf[40]; int result; @@ -724,22 +723,23 @@ static void __init do_initcalls(void) (unsigned long long) delta.tv64 >> 20); } - if (result && result != -ENODEV && initcall_debug) { - sprintf(msgbuf, "error code %d", result); - msg = msgbuf; - } + msgbuf[0] = 0; + + if (result && result != -ENODEV && initcall_debug) + sprintf(msgbuf, "error code %d ", result); + if (preempt_count() != count) { - msg = "preemption imbalance"; + strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf)); preempt_count() = count; } if (irqs_disabled()) { - msg = "disabled interrupts"; + strncat(msgbuf, "disabled interrupts ", sizeof(msgbuf)); local_irq_enable(); } - if (msg) { + if (msgbuf[0]) { print_fn_descriptor_symbol(KERN_WARNING "initcall %s()", (unsigned long) *call); - printk(" returned with %s\n", msg); + printk(" returned with %s\n", msgbuf); } } -- cgit v1.1 From f38c84312748de9d04562c12af57080c6901f931 Mon Sep 17 00:00:00 2001 From: Greg Ungerer Date: Mon, 12 May 2008 14:02:23 -0700 Subject: m68knommu: missing sections for linker script Include the missing kcrctab and kcrctab_unused sections into the m68knommu linker script. Signed-off-by: Greg Ungerer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/m68knommu/kernel/vmlinux.lds.S | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/m68knommu/kernel/vmlinux.lds.S b/arch/m68knommu/kernel/vmlinux.lds.S index 5592e0b..93e69236 100644 --- a/arch/m68knommu/kernel/vmlinux.lds.S +++ b/arch/m68knommu/kernel/vmlinux.lds.S @@ -114,6 +114,16 @@ SECTIONS { *(__kcrctab_gpl) __stop___kcrctab_gpl = .; + /* Kernel symbol table: Normal unused symbols */ + __start___kcrctab_unused = .; + *(__kcrctab_unused) + __stop___kcrctab_unused = .; + + /* Kernel symbol table: GPL-only unused symbols */ + __start___kcrctab_unused_gpl = .; + *(__kcrctab_unused_gpl) + __stop___kcrctab_unused_gpl = .; + /* Kernel symbol table: GPL-future symbols */ __start___kcrctab_gpl_future = .; *(__kcrctab_gpl_future) -- cgit v1.1 From 945185a69daa457c4c5e46e47f4afad7dcea734f Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 12 May 2008 14:02:24 -0700 Subject: rtc: rtc_time_to_tm: use unsigned arithmetic The input argument to rtc_time_to_tm() is unsigned as well as are members of the output structure. However signed arithmetic is used within for calculations leading to incorrect results for input values outside the signed positive range. If this happens the time of day returned is out of range. Found the problem when fiddling with the RTC and the driver where year was set to an unexpectedly large value like 2070, e.g.: rtc0: setting system clock to 2070-01-01 1193046:71582832:26 UTC (3155760954) while it should be: rtc0: setting system clock to 2070-01-01 00:15:54 UTC (3155760954) Changing types to unsigned fixes the problem. [akpm@linux-foundation.org: remove old-fashioned `register' keyword] Signed-off-by: Maciej W. Rozycki Cc: Alessandro Zummo Cc: David Brownell Cc: Dmitri Vorobiev Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-lib.c b/drivers/rtc/rtc-lib.c index ba795a4..9f996ec 100644 --- a/drivers/rtc/rtc-lib.c +++ b/drivers/rtc/rtc-lib.c @@ -51,7 +51,7 @@ EXPORT_SYMBOL(rtc_year_days); */ void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) { - register int days, month, year; + unsigned int days, month, year; days = time / 86400; time -= days * 86400; -- cgit v1.1 From baf6332a238a680ef3add9cfb0729f136da886b8 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Mon, 12 May 2008 14:02:25 -0700 Subject: atmel_lcdfb: fix pixclock divider calculation Fix divider calculation and allow CLKVAL = 0 (divisor 2) It was not possible to get the clock value 0 (divisor 2) because the test "<=0" force the BYPASS bit to be activated instead. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Nicolas Ferre Cc: Per Hedblom Cc: Roel Kluin <12o3l@tiscali.nl> Cc: Jan Weber Cc: Andrew Victor Cc: Haavard Skinnemoen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/atmel_lcdfb.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 8ffdf35..b004036 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c @@ -441,14 +441,15 @@ static int atmel_lcdfb_set_par(struct fb_info *info) value = DIV_ROUND_UP(clk_value_khz, PICOS2KHZ(info->var.pixclock)); - value = (value / 2) - 1; - dev_dbg(info->device, " * programming CLKVAL = 0x%08lx\n", value); - - if (value <= 0) { + if (value < 2) { dev_notice(info->device, "Bypassing pixel clock divider\n"); lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, ATMEL_LCDC_BYPASS); } else { - lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, value << ATMEL_LCDC_CLKVAL_OFFSET); + value = (value / 2) - 1; + dev_dbg(info->device, " * programming CLKVAL = 0x%08lx\n", + value); + lcdc_writel(sinfo, ATMEL_LCDC_LCDCON1, + value << ATMEL_LCDC_CLKVAL_OFFSET); info->var.pixclock = KHZ2PICOS(clk_value_khz / (2 * (value + 1))); dev_dbg(info->device, " updated pixclk: %lu KHz\n", PICOS2KHZ(info->var.pixclock)); -- cgit v1.1 From 53c78dd1718b99dc365ff8a2244d7d4504b070a5 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 12 May 2008 14:02:28 -0700 Subject: fbdev: do not let CONFIG_FB_DEFERRED_IO default to y CONFIG_FB_DEFERRED_IO can not be turned off, while it's already selected automatically by the drivers that need it. Although it's nice to have more compile-coverage, not being able to disable a rarely used feature is annoying. Signed-off-by: Geert Uytterhoeven Acked-by: Jaya Kumar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index bb1dada..2cdaf1f 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -171,7 +171,6 @@ config FB_SYS_FOPS config FB_DEFERRED_IO bool depends on FB - default y config FB_METRONOME tristate -- cgit v1.1 From f4ed0deae8983591264d0e194e168ef65f4775f5 Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Mon, 12 May 2008 14:02:29 -0700 Subject: cpumask: remove bitmap_scnprintf_len and cpumask_scnprintf_len They aren't used. They were briefly used as part of some other patches to provide an alternative format for displaying some /proc and /sys cpumasks. They probably should have been removed when those other patches were dropped, in favor of a different solution. Signed-off-by: Paul Jackson Cc: "Mike Travis" Cc: "Bert Wesarg" Cc: Alexey Dobriyan Cc: WANG Cong Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/bitmap.h | 1 - include/linux/cpumask.h | 7 ------- lib/bitmap.c | 16 ---------------- 3 files changed, 24 deletions(-) diff --git a/include/linux/bitmap.h b/include/linux/bitmap.h index 43b406d..1abfe66 100644 --- a/include/linux/bitmap.h +++ b/include/linux/bitmap.h @@ -110,7 +110,6 @@ extern int __bitmap_weight(const unsigned long *bitmap, int bits); extern int bitmap_scnprintf(char *buf, unsigned int len, const unsigned long *src, int nbits); -extern int bitmap_scnprintf_len(unsigned int len); extern int __bitmap_parse(const char *buf, unsigned int buflen, int is_user, unsigned long *dst, int nbits); extern int bitmap_parse_user(const char __user *ubuf, unsigned int ulen, diff --git a/include/linux/cpumask.h b/include/linux/cpumask.h index 9650806..5df3db5 100644 --- a/include/linux/cpumask.h +++ b/include/linux/cpumask.h @@ -289,13 +289,6 @@ static inline int __cpumask_scnprintf(char *buf, int len, return bitmap_scnprintf(buf, len, srcp->bits, nbits); } -#define cpumask_scnprintf_len(len) \ - __cpumask_scnprintf_len((len)) -static inline int __cpumask_scnprintf_len(int len) -{ - return bitmap_scnprintf_len(len); -} - #define cpumask_parse_user(ubuf, ulen, dst) \ __cpumask_parse_user((ubuf), (ulen), &(dst), NR_CPUS) static inline int __cpumask_parse_user(const char __user *buf, int len, diff --git a/lib/bitmap.c b/lib/bitmap.c index c4cb48f..482df94 100644 --- a/lib/bitmap.c +++ b/lib/bitmap.c @@ -316,22 +316,6 @@ int bitmap_scnprintf(char *buf, unsigned int buflen, EXPORT_SYMBOL(bitmap_scnprintf); /** - * bitmap_scnprintf_len - return buffer length needed to convert - * bitmap to an ASCII hex string. - * @len: number of bits to be converted - */ -int bitmap_scnprintf_len(unsigned int len) -{ - /* we need 9 chars per word for 32 bit words (8 hexdigits + sep/null) */ - int bitslen = ALIGN(len, CHUNKSZ); - int wordlen = CHUNKSZ / 4; - int buflen = (bitslen / wordlen) * (wordlen + 1) * sizeof(char); - - return buflen; -} -EXPORT_SYMBOL(bitmap_scnprintf_len); - -/** * __bitmap_parse - convert an ASCII hex string into a bitmap. * @buf: pointer to buffer containing string. * @buflen: buffer size in bytes. If string is smaller than this -- cgit v1.1 From c9bfcb3151040cff6714542d1da04ccd7e2d3efc Mon Sep 17 00:00:00 2001 From: Joakim Tjernlund Date: Mon, 12 May 2008 14:02:30 -0700 Subject: spi_mpc83xx: much improved driver The current driver may cause glitches on SPI CLK line since one must disable the SPI controller before changing any HW settings. Fix this by implementing a local spi_transfer function that won't change speed and/or word size while CS is active. While doing that heavy lifting a few other issues were addressed too: - Make word size 16 and 32 work too. - Honor bits_per_word and speed_hz in spi transaction. - Optimize the common path. This also stops using the "bitbang" framework (except for a few constants). [Roel Kluin <12o3l@tiscali.nl>: "irq" needs to be signed] Signed-off-by: Joakim Tjernlund Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/Kconfig | 1 - drivers/spi/spi_mpc83xx.c | 411 +++++++++++++++++++++++++++++++--------------- 2 files changed, 282 insertions(+), 130 deletions(-) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index fae9e8f..66ec5d8 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -126,7 +126,6 @@ config SPI_MPC52xx_PSC config SPI_MPC83xx tristate "Freescale MPC83xx/QUICC Engine SPI controller" depends on SPI_MASTER && (PPC_83xx || QUICC_ENGINE) && EXPERIMENTAL - select SPI_BITBANG help This enables using the Freescale MPC83xx and QUICC Engine SPI controllers in master mode. diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c index 189f706..6832da6 100644 --- a/drivers/spi/spi_mpc83xx.c +++ b/drivers/spi/spi_mpc83xx.c @@ -49,6 +49,7 @@ struct mpc83xx_spi_reg { #define SPMODE_LEN(x) ((x) << 20) #define SPMODE_PM(x) ((x) << 16) #define SPMODE_OP (1 << 14) +#define SPMODE_CG(x) ((x) << 7) /* * Default for SPI Mode: @@ -67,10 +68,6 @@ struct mpc83xx_spi_reg { /* SPI Controller driver's private data. */ struct mpc83xx_spi { - /* bitbang has to be first */ - struct spi_bitbang bitbang; - struct completion done; - struct mpc83xx_spi_reg __iomem *base; /* rx & tx bufs from the spi_transfer */ @@ -82,7 +79,7 @@ struct mpc83xx_spi { u32(*get_tx) (struct mpc83xx_spi *); unsigned int count; - u32 irq; + int irq; unsigned nsecs; /* (clock cycle time)/2 */ @@ -94,6 +91,25 @@ struct mpc83xx_spi { void (*activate_cs) (u8 cs, u8 polarity); void (*deactivate_cs) (u8 cs, u8 polarity); + + u8 busy; + + struct workqueue_struct *workqueue; + struct work_struct work; + + struct list_head queue; + spinlock_t lock; + + struct completion done; +}; + +struct spi_mpc83xx_cs { + /* functions to deal with different sized buffers */ + void (*get_rx) (u32 rx_data, struct mpc83xx_spi *); + u32 (*get_tx) (struct mpc83xx_spi *); + u32 rx_shift; /* RX data reg shift when in qe mode */ + u32 tx_shift; /* TX data reg shift when in qe mode */ + u32 hw_mode; /* Holds HW mode register settings */ }; static inline void mpc83xx_spi_write_reg(__be32 __iomem * reg, u32 val) @@ -137,6 +153,7 @@ static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) { struct mpc83xx_spi *mpc83xx_spi; u8 pol = spi->mode & SPI_CS_HIGH ? 1 : 0; + struct spi_mpc83xx_cs *cs = spi->controller_state; mpc83xx_spi = spi_master_get_devdata(spi->master); @@ -147,50 +164,26 @@ static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) if (value == BITBANG_CS_ACTIVE) { u32 regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode); - u32 len = spi->bits_per_word; - u8 pm; - if (len == 32) - len = 0; - else - len = len - 1; - - /* mask out bits we are going to set */ - regval &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH - | SPMODE_LEN(0xF) | SPMODE_DIV16 - | SPMODE_PM(0xF) | SPMODE_REV | SPMODE_LOOP); - - if (spi->mode & SPI_CPHA) - regval |= SPMODE_CP_BEGIN_EDGECLK; - if (spi->mode & SPI_CPOL) - regval |= SPMODE_CI_INACTIVEHIGH; - if (!(spi->mode & SPI_LSB_FIRST)) - regval |= SPMODE_REV; - if (spi->mode & SPI_LOOP) - regval |= SPMODE_LOOP; - - regval |= SPMODE_LEN(len); - - if ((mpc83xx_spi->spibrg / spi->max_speed_hz) >= 64) { - pm = mpc83xx_spi->spibrg / (spi->max_speed_hz * 64) - 1; - if (pm > 0x0f) { - dev_err(&spi->dev, "Requested speed is too " - "low: %d Hz. Will use %d Hz instead.\n", - spi->max_speed_hz, - mpc83xx_spi->spibrg / 1024); - pm = 0x0f; - } - regval |= SPMODE_PM(pm) | SPMODE_DIV16; - } else { - pm = mpc83xx_spi->spibrg / (spi->max_speed_hz * 4); - if (pm) - pm--; - regval |= SPMODE_PM(pm); + mpc83xx_spi->rx_shift = cs->rx_shift; + mpc83xx_spi->tx_shift = cs->tx_shift; + mpc83xx_spi->get_rx = cs->get_rx; + mpc83xx_spi->get_tx = cs->get_tx; + + if (cs->hw_mode != regval) { + unsigned long flags; + void *tmp_ptr = &mpc83xx_spi->base->mode; + + regval = cs->hw_mode; + /* Turn off IRQs locally to minimize time that + * SPI is disabled + */ + local_irq_save(flags); + /* Turn off SPI unit prior changing mode */ + mpc83xx_spi_write_reg(tmp_ptr, regval & ~SPMODE_ENABLE); + mpc83xx_spi_write_reg(tmp_ptr, regval); + local_irq_restore(flags); } - - /* Turn off SPI unit prior changing mode */ - mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, 0); - mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval); if (mpc83xx_spi->activate_cs) mpc83xx_spi->activate_cs(spi->chip_select, pol); } @@ -201,8 +194,9 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) { struct mpc83xx_spi *mpc83xx_spi; u32 regval; - u8 bits_per_word; + u8 bits_per_word, pm; u32 hz; + struct spi_mpc83xx_cs *cs = spi->controller_state; mpc83xx_spi = spi_master_get_devdata(spi->master); @@ -223,61 +217,191 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) || ((bits_per_word > 16) && (bits_per_word != 32))) return -EINVAL; - mpc83xx_spi->rx_shift = 0; - mpc83xx_spi->tx_shift = 0; + if (!hz) + hz = spi->max_speed_hz; + + cs->rx_shift = 0; + cs->tx_shift = 0; if (bits_per_word <= 8) { - mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8; - mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8; + cs->get_rx = mpc83xx_spi_rx_buf_u8; + cs->get_tx = mpc83xx_spi_tx_buf_u8; if (mpc83xx_spi->qe_mode) { - mpc83xx_spi->rx_shift = 16; - mpc83xx_spi->tx_shift = 24; + cs->rx_shift = 16; + cs->tx_shift = 24; } } else if (bits_per_word <= 16) { - mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u16; - mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u16; + cs->get_rx = mpc83xx_spi_rx_buf_u16; + cs->get_tx = mpc83xx_spi_tx_buf_u16; if (mpc83xx_spi->qe_mode) { - mpc83xx_spi->rx_shift = 16; - mpc83xx_spi->tx_shift = 16; + cs->rx_shift = 16; + cs->tx_shift = 16; } } else if (bits_per_word <= 32) { - mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u32; - mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u32; + cs->get_rx = mpc83xx_spi_rx_buf_u32; + cs->get_tx = mpc83xx_spi_tx_buf_u32; } else return -EINVAL; if (mpc83xx_spi->qe_mode && spi->mode & SPI_LSB_FIRST) { - mpc83xx_spi->tx_shift = 0; + cs->tx_shift = 0; if (bits_per_word <= 8) - mpc83xx_spi->rx_shift = 8; + cs->rx_shift = 8; else - mpc83xx_spi->rx_shift = 0; + cs->rx_shift = 0; } - /* nsecs = (clock period)/2 */ - if (!hz) - hz = spi->max_speed_hz; - mpc83xx_spi->nsecs = (1000000000 / 2) / hz; - if (mpc83xx_spi->nsecs > MAX_UDELAY_MS * 1000) - return -EINVAL; + mpc83xx_spi->rx_shift = cs->rx_shift; + mpc83xx_spi->tx_shift = cs->tx_shift; + mpc83xx_spi->get_rx = cs->get_rx; + mpc83xx_spi->get_tx = cs->get_tx; if (bits_per_word == 32) bits_per_word = 0; else bits_per_word = bits_per_word - 1; - regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode); - /* mask out bits we are going to set */ - regval &= ~(SPMODE_LEN(0xF) | SPMODE_REV); - regval |= SPMODE_LEN(bits_per_word); - if (!(spi->mode & SPI_LSB_FIRST)) - regval |= SPMODE_REV; + cs->hw_mode &= ~(SPMODE_LEN(0xF) | SPMODE_DIV16 + | SPMODE_PM(0xF)); + + cs->hw_mode |= SPMODE_LEN(bits_per_word); + + if ((mpc83xx_spi->spibrg / hz) >= 64) { + pm = mpc83xx_spi->spibrg / (hz * 64) - 1; + if (pm > 0x0f) { + dev_err(&spi->dev, "Requested speed is too " + "low: %d Hz. Will use %d Hz instead.\n", + hz, mpc83xx_spi->spibrg / 1024); + pm = 0x0f; + } + cs->hw_mode |= SPMODE_PM(pm) | SPMODE_DIV16; + } else { + pm = mpc83xx_spi->spibrg / (hz * 4); + if (pm) + pm--; + cs->hw_mode |= SPMODE_PM(pm); + } + regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode); + if (cs->hw_mode != regval) { + unsigned long flags; + void *tmp_ptr = &mpc83xx_spi->base->mode; + + regval = cs->hw_mode; + /* Turn off IRQs locally to minimize time + * that SPI is disabled + */ + local_irq_save(flags); + /* Turn off SPI unit prior changing mode */ + mpc83xx_spi_write_reg(tmp_ptr, regval & ~SPMODE_ENABLE); + mpc83xx_spi_write_reg(tmp_ptr, regval); + local_irq_restore(flags); + } + return 0; +} - /* Turn off SPI unit prior changing mode */ - mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, 0); - mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval); +static int mpc83xx_spi_bufs(struct spi_device *spi, struct spi_transfer *t) +{ + struct mpc83xx_spi *mpc83xx_spi; + u32 word, len, bits_per_word; - return 0; + mpc83xx_spi = spi_master_get_devdata(spi->master); + + mpc83xx_spi->tx = t->tx_buf; + mpc83xx_spi->rx = t->rx_buf; + bits_per_word = spi->bits_per_word; + if (t->bits_per_word) + bits_per_word = t->bits_per_word; + len = t->len; + if (bits_per_word > 8) + len /= 2; + if (bits_per_word > 16) + len /= 2; + mpc83xx_spi->count = len; + INIT_COMPLETION(mpc83xx_spi->done); + + /* enable rx ints */ + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, SPIM_NE); + + /* transmit word */ + word = mpc83xx_spi->get_tx(mpc83xx_spi); + mpc83xx_spi_write_reg(&mpc83xx_spi->base->transmit, word); + + wait_for_completion(&mpc83xx_spi->done); + + /* disable rx ints */ + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, 0); + + return mpc83xx_spi->count; +} + +static void mpc83xx_spi_work(struct work_struct *work) +{ + struct mpc83xx_spi *mpc83xx_spi = + container_of(work, struct mpc83xx_spi, work); + + spin_lock_irq(&mpc83xx_spi->lock); + mpc83xx_spi->busy = 1; + while (!list_empty(&mpc83xx_spi->queue)) { + struct spi_message *m; + struct spi_device *spi; + struct spi_transfer *t = NULL; + unsigned cs_change; + int status, nsecs = 50; + + m = container_of(mpc83xx_spi->queue.next, + struct spi_message, queue); + list_del_init(&m->queue); + spin_unlock_irq(&mpc83xx_spi->lock); + + spi = m->spi; + cs_change = 1; + status = 0; + list_for_each_entry(t, &m->transfers, transfer_list) { + if (t->bits_per_word || t->speed_hz) { + /* Don't allow changes if CS is active */ + status = -EINVAL; + + if (cs_change) + status = mpc83xx_spi_setup_transfer(spi, t); + if (status < 0) + break; + } + + if (cs_change) + mpc83xx_spi_chipselect(spi, BITBANG_CS_ACTIVE); + cs_change = t->cs_change; + if (t->len) + status = mpc83xx_spi_bufs(spi, t); + if (status) { + status = -EMSGSIZE; + break; + } + m->actual_length += t->len; + + if (t->delay_usecs) + udelay(t->delay_usecs); + + if (cs_change) { + ndelay(nsecs); + mpc83xx_spi_chipselect(spi, BITBANG_CS_INACTIVE); + ndelay(nsecs); + } + } + + m->status = status; + m->complete(m->context); + + if (status || !cs_change) { + ndelay(nsecs); + mpc83xx_spi_chipselect(spi, BITBANG_CS_INACTIVE); + } + + mpc83xx_spi_setup_transfer(spi, NULL); + + spin_lock_irq(&mpc83xx_spi->lock); + } + mpc83xx_spi->busy = 0; + spin_unlock_irq(&mpc83xx_spi->lock); } /* the spi->mode bits understood by this driver: */ @@ -286,9 +410,10 @@ int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) static int mpc83xx_spi_setup(struct spi_device *spi) { - struct spi_bitbang *bitbang; struct mpc83xx_spi *mpc83xx_spi; int retval; + u32 hw_mode; + struct spi_mpc83xx_cs *cs = spi->controller_state; if (spi->mode & ~MODEBITS) { dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n", @@ -299,63 +424,56 @@ static int mpc83xx_spi_setup(struct spi_device *spi) if (!spi->max_speed_hz) return -EINVAL; - bitbang = spi_master_get_devdata(spi->master); + if (!cs) { + cs = kzalloc(sizeof *cs, GFP_KERNEL); + if (!cs) + return -ENOMEM; + spi->controller_state = cs; + } mpc83xx_spi = spi_master_get_devdata(spi->master); if (!spi->bits_per_word) spi->bits_per_word = 8; + hw_mode = cs->hw_mode; /* Save orginal settings */ + cs->hw_mode = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode); + /* mask out bits we are going to set */ + cs->hw_mode &= ~(SPMODE_CP_BEGIN_EDGECLK | SPMODE_CI_INACTIVEHIGH + | SPMODE_REV | SPMODE_LOOP); + + if (spi->mode & SPI_CPHA) + cs->hw_mode |= SPMODE_CP_BEGIN_EDGECLK; + if (spi->mode & SPI_CPOL) + cs->hw_mode |= SPMODE_CI_INACTIVEHIGH; + if (!(spi->mode & SPI_LSB_FIRST)) + cs->hw_mode |= SPMODE_REV; + if (spi->mode & SPI_LOOP) + cs->hw_mode |= SPMODE_LOOP; + retval = mpc83xx_spi_setup_transfer(spi, NULL); - if (retval < 0) + if (retval < 0) { + cs->hw_mode = hw_mode; /* Restore settings */ return retval; + } - dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n", + dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u Hz\n", __func__, spi->mode & (SPI_CPOL | SPI_CPHA), - spi->bits_per_word, 2 * mpc83xx_spi->nsecs); - + spi->bits_per_word, spi->max_speed_hz); +#if 0 /* Don't think this is needed */ /* NOTE we _need_ to call chipselect() early, ideally with adapter * setup, unless the hardware defaults cooperate to avoid confusion * between normal (active low) and inverted chipselects. */ /* deselect chip (low or high) */ - spin_lock(&bitbang->lock); - if (!bitbang->busy) { - bitbang->chipselect(spi, BITBANG_CS_INACTIVE); - ndelay(mpc83xx_spi->nsecs); - } - spin_unlock(&bitbang->lock); - + spin_lock(&mpc83xx_spi->lock); + if (!mpc83xx_spi->busy) + mpc83xx_spi_chipselect(spi, BITBANG_CS_INACTIVE); + spin_unlock(&mpc83xx_spi->lock); +#endif return 0; } -static int mpc83xx_spi_bufs(struct spi_device *spi, struct spi_transfer *t) -{ - struct mpc83xx_spi *mpc83xx_spi; - u32 word; - - mpc83xx_spi = spi_master_get_devdata(spi->master); - - mpc83xx_spi->tx = t->tx_buf; - mpc83xx_spi->rx = t->rx_buf; - mpc83xx_spi->count = t->len; - INIT_COMPLETION(mpc83xx_spi->done); - - /* enable rx ints */ - mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, SPIM_NE); - - /* transmit word */ - word = mpc83xx_spi->get_tx(mpc83xx_spi); - mpc83xx_spi_write_reg(&mpc83xx_spi->base->transmit, word); - - wait_for_completion(&mpc83xx_spi->done); - - /* disable rx ints */ - mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, 0); - - return t->len - mpc83xx_spi->count; -} - irqreturn_t mpc83xx_spi_irq(s32 irq, void *context_data) { struct mpc83xx_spi *mpc83xx_spi = context_data; @@ -395,6 +513,28 @@ irqreturn_t mpc83xx_spi_irq(s32 irq, void *context_data) return ret; } +static int mpc83xx_spi_transfer(struct spi_device *spi, + struct spi_message *m) +{ + struct mpc83xx_spi *mpc83xx_spi = spi_master_get_devdata(spi->master); + unsigned long flags; + + m->actual_length = 0; + m->status = -EINPROGRESS; + + spin_lock_irqsave(&mpc83xx_spi->lock, flags); + list_add_tail(&m->queue, &mpc83xx_spi->queue); + queue_work(mpc83xx_spi->workqueue, &mpc83xx_spi->work); + spin_unlock_irqrestore(&mpc83xx_spi->lock, flags); + + return 0; +} + + +static void mpc83xx_spi_cleanup(struct spi_device *spi) +{ + kfree(spi->controller_state); +} static int __init mpc83xx_spi_probe(struct platform_device *dev) { @@ -426,11 +566,11 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) ret = -ENODEV; goto free_master; } + master->setup = mpc83xx_spi_setup; + master->transfer = mpc83xx_spi_transfer; + master->cleanup = mpc83xx_spi_cleanup; + mpc83xx_spi = spi_master_get_devdata(master); - mpc83xx_spi->bitbang.master = spi_master_get(master); - mpc83xx_spi->bitbang.chipselect = mpc83xx_spi_chipselect; - mpc83xx_spi->bitbang.setup_transfer = mpc83xx_spi_setup_transfer; - mpc83xx_spi->bitbang.txrx_bufs = mpc83xx_spi_bufs; mpc83xx_spi->activate_cs = pdata->activate_cs; mpc83xx_spi->deactivate_cs = pdata->deactivate_cs; mpc83xx_spi->qe_mode = pdata->qe_mode; @@ -445,7 +585,6 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) mpc83xx_spi->tx_shift = 24; } - mpc83xx_spi->bitbang.master->setup = mpc83xx_spi_setup; init_completion(&mpc83xx_spi->done); mpc83xx_spi->base = ioremap(r->start, r->end - r->start + 1); @@ -483,11 +622,21 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) regval |= SPMODE_OP; mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval); + spin_lock_init(&mpc83xx_spi->lock); + init_completion(&mpc83xx_spi->done); + INIT_WORK(&mpc83xx_spi->work, mpc83xx_spi_work); + INIT_LIST_HEAD(&mpc83xx_spi->queue); - ret = spi_bitbang_start(&mpc83xx_spi->bitbang); - - if (ret != 0) + mpc83xx_spi->workqueue = create_singlethread_workqueue( + master->dev.parent->bus_id); + if (mpc83xx_spi->workqueue == NULL) { + ret = -EBUSY; goto free_irq; + } + + ret = spi_register_master(master); + if (ret < 0) + goto unreg_master; printk(KERN_INFO "%s: MPC83xx SPI Controller driver at 0x%p (irq = %d)\n", @@ -495,6 +644,8 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) return ret; +unreg_master: + destroy_workqueue(mpc83xx_spi->workqueue); free_irq: free_irq(mpc83xx_spi->irq, mpc83xx_spi); unmap_io: @@ -515,10 +666,12 @@ static int __exit mpc83xx_spi_remove(struct platform_device *dev) master = platform_get_drvdata(dev); mpc83xx_spi = spi_master_get_devdata(master); - spi_bitbang_stop(&mpc83xx_spi->bitbang); + flush_workqueue(mpc83xx_spi->workqueue); + destroy_workqueue(mpc83xx_spi->workqueue); + spi_unregister_master(master); + free_irq(mpc83xx_spi->irq, mpc83xx_spi); iounmap(mpc83xx_spi->base); - spi_master_put(mpc83xx_spi->bitbang.master); return 0; } -- cgit v1.1 From 4cd1a8fc3d3cd740416b14ece2693dbb5d065eaf Mon Sep 17 00:00:00 2001 From: KOSAKI Motohiro Date: Mon, 12 May 2008 14:02:31 -0700 Subject: memcg: fix possible panic when CONFIG_MM_OWNER=y When mm destruction happens, we should pass mm_update_next_owner() the old mm. But unfortunately new mm is passed in exec_mmap(). Thus, kernel panic is possible when a multi-threaded process uses exec(). Also, the owner member comment description is wrong. mm->owner does not necessarily point to the thread group leader. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: KOSAKI Motohiro Acked-by: Balbir Singh Cc: "Paul Menage" Cc: "KAMEZAWA Hiroyuki" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 2 +- include/linux/mm_types.h | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/fs/exec.c b/fs/exec.c index aeaa979..1f8a24a 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -736,7 +736,7 @@ static int exec_mmap(struct mm_struct *mm) tsk->active_mm = mm; activate_mm(active_mm, mm); task_unlock(tsk); - mm_update_next_owner(mm); + mm_update_next_owner(old_mm); arch_pick_mmap_layout(mm); if (old_mm) { up_read(&old_mm->mmap_sem); diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index eb7c16c..02a27ae 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -226,8 +226,17 @@ struct mm_struct { rwlock_t ioctx_list_lock; /* aio lock */ struct kioctx *ioctx_list; #ifdef CONFIG_MM_OWNER - struct task_struct *owner; /* The thread group leader that */ - /* owns the mm_struct. */ + /* + * "owner" points to a task that is regarded as the canonical + * user/owner of this mm. All of the following must be true in + * order for it to be changed: + * + * current == mm->owner + * current->mm != mm + * new_owner->mm == mm + * new_owner->alloc_lock is held + */ + struct task_struct *owner; #endif #ifdef CONFIG_PROC_FS -- cgit v1.1 From 0f146a764ff08c4c210c04239c5e6784b4b77485 Mon Sep 17 00:00:00 2001 From: Dhaval Giani Date: Mon, 12 May 2008 14:02:31 -0700 Subject: cgroups: fix documentation Correct the cgroups documentation to reflect the correct file names. Signed-off-by: Dhaval Giani Cc: Sudhir Kumar Cc: Balbir Singh Cc: KAMEZAWA Hiroyuki Acked-by: Paul Menage Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/cgroups.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/cgroups.txt b/Documentation/cgroups.txt index c298a66..824fc02 100644 --- a/Documentation/cgroups.txt +++ b/Documentation/cgroups.txt @@ -310,8 +310,8 @@ and then start a subshell 'sh' in that cgroup: cd /dev/cgroup mkdir Charlie cd Charlie - /bin/echo 2-3 > cpus - /bin/echo 1 > mems + /bin/echo 2-3 > cpuset.cpus + /bin/echo 1 > cpuset.mems /bin/echo $$ > tasks sh # The subshell 'sh' is now running in cgroup Charlie -- cgit v1.1 From 78bb6cb9a890d3d50ca3b02fce9223d3e734ab9b Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 12 May 2008 14:02:32 -0700 Subject: fuse: add flag to turn on big writes Prior to 2.6.26 fuse only supported single page write requests. In theory all fuse filesystem should be able support bigger than 4k writes, as there's nothing in the API to prevent it. Unfortunately there's a known case in NTFS-3G where big writes cause filesystem corruption. There could also be other filesystems, where the lack of testing with big write requests would result in bugs. To prevent such problems on a kernel upgrade, disable big writes by default, but let filesystems set a flag to turn it on. Signed-off-by: Miklos Szeredi Cc: Szabolcs Szakacsits Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/file.c | 2 ++ fs/fuse/fuse_i.h | 3 +++ fs/fuse/inode.c | 5 ++++- include/linux/fuse.h | 1 + 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index f28cf8b..8092f0d 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -804,6 +804,8 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, if (offset == PAGE_CACHE_SIZE) offset = 0; + if (!fc->big_writes) + break; } while (iov_iter_count(ii) && count < fc->max_write && req->num_pages < FUSE_MAX_PAGES_PER_REQ && offset == 0); diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index dadffa2..bae9486 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -404,6 +404,9 @@ struct fuse_conn { /** Is bmap not implemented by fs? */ unsigned no_bmap : 1; + /** Do multi-page cached writes */ + unsigned big_writes : 1; + /** The number of requests waiting for completion */ atomic_t num_waiting; diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 79b6158..fb77e09 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c @@ -576,6 +576,8 @@ static void process_init_reply(struct fuse_conn *fc, struct fuse_req *req) fc->no_lock = 1; if (arg->flags & FUSE_ATOMIC_O_TRUNC) fc->atomic_o_trunc = 1; + if (arg->flags & FUSE_BIG_WRITES) + fc->big_writes = 1; } else { ra_pages = fc->max_read / PAGE_CACHE_SIZE; fc->no_lock = 1; @@ -599,7 +601,8 @@ static void fuse_send_init(struct fuse_conn *fc, struct fuse_req *req) arg->major = FUSE_KERNEL_VERSION; arg->minor = FUSE_KERNEL_MINOR_VERSION; arg->max_readahead = fc->bdi.ra_pages * PAGE_CACHE_SIZE; - arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC; + arg->flags |= FUSE_ASYNC_READ | FUSE_POSIX_LOCKS | FUSE_ATOMIC_O_TRUNC | + FUSE_BIG_WRITES; req->in.h.opcode = FUSE_INIT; req->in.numargs = 1; req->in.args[0].size = sizeof(*arg); diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 5c86f11..d482821 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -109,6 +109,7 @@ struct fuse_file_lock { #define FUSE_POSIX_LOCKS (1 << 1) #define FUSE_FILE_OPS (1 << 2) #define FUSE_ATOMIC_O_TRUNC (1 << 3) +#define FUSE_BIG_WRITES (1 << 5) /** * Release flags -- cgit v1.1 From f36f21ecca9ee688301174e5f2e0827827a7a7ff Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 12 May 2008 14:02:33 -0700 Subject: Fix misuses of bdevname() bdevname() fills the buffer that it is given as a parameter, so calling strcpy() or snprintf() on the returned value is redundant (and probably not guaranteed to work - I don't think strcpy and snprintf support overlapping buffers.) Signed-off-by: Jean Delvare Cc: Stephen Tweedie Cc: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- block/blktrace.c | 2 +- block/compat_ioctl.c | 2 +- fs/ext4/mballoc.c | 6 ++---- fs/jbd2/journal.c | 4 ++-- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/block/blktrace.c b/block/blktrace.c index 568588c..b2cbb4e 100644 --- a/block/blktrace.c +++ b/block/blktrace.c @@ -476,7 +476,7 @@ int blk_trace_ioctl(struct block_device *bdev, unsigned cmd, char __user *arg) switch (cmd) { case BLKTRACESETUP: - strcpy(b, bdevname(bdev, b)); + bdevname(bdev, b); ret = blk_trace_setup(q, b, bdev->bd_dev, arg); break; case BLKTRACESTART: diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c index c70d0b6..c23177e 100644 --- a/block/compat_ioctl.c +++ b/block/compat_ioctl.c @@ -555,7 +555,7 @@ static int compat_blk_trace_setup(struct block_device *bdev, char __user *arg) if (copy_from_user(&cbuts, arg, sizeof(cbuts))) return -EFAULT; - strcpy(b, bdevname(bdev, b)); + bdevname(bdev, b); buts = (struct blk_user_trace_setup) { .act_mask = cbuts.act_mask, diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index fbec2ef..b128bdc 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -2639,8 +2639,7 @@ static int ext4_mb_init_per_dev_proc(struct super_block *sb) struct proc_dir_entry *proc; char devname[64]; - snprintf(devname, sizeof(devname) - 1, "%s", - bdevname(sb->s_bdev, devname)); + bdevname(sb->s_bdev, devname); sbi->s_mb_proc = proc_mkdir(devname, proc_root_ext4); MB_PROC_HANDLER(EXT4_MB_STATS_NAME, stats); @@ -2674,8 +2673,7 @@ static int ext4_mb_destroy_per_dev_proc(struct super_block *sb) if (sbi->s_mb_proc == NULL) return -EINVAL; - snprintf(devname, sizeof(devname) - 1, "%s", - bdevname(sb->s_bdev, devname)); + bdevname(sb->s_bdev, devname); remove_proc_entry(EXT4_MB_GROUP_PREALLOC, sbi->s_mb_proc); remove_proc_entry(EXT4_MB_STREAM_REQ, sbi->s_mb_proc); remove_proc_entry(EXT4_MB_ORDER2_REQ, sbi->s_mb_proc); diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index 53632e3..2e24567 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -901,7 +901,7 @@ static void jbd2_stats_proc_init(journal_t *journal) { char name[BDEVNAME_SIZE]; - snprintf(name, sizeof(name) - 1, "%s", bdevname(journal->j_dev, name)); + bdevname(journal->j_dev, name); journal->j_proc_entry = proc_mkdir(name, proc_jbd2_stats); if (journal->j_proc_entry) { proc_create_data("history", S_IRUGO, journal->j_proc_entry, @@ -915,7 +915,7 @@ static void jbd2_stats_proc_exit(journal_t *journal) { char name[BDEVNAME_SIZE]; - snprintf(name, sizeof(name) - 1, "%s", bdevname(journal->j_dev, name)); + bdevname(journal->j_dev, name); remove_proc_entry("info", journal->j_proc_entry); remove_proc_entry("history", journal->j_proc_entry); remove_proc_entry(name, proc_jbd2_stats); -- cgit v1.1 From 6c82c4150910dedd449194cb6d286b80478f3542 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 12 May 2008 14:02:34 -0700 Subject: drivers/char/synclink_gt.c: don't return an uninitialised local drivers/char/synclink_gt.c: In function 'put_char': drivers/char/synclink_gt.c:919: warning: 'ret' may be used uninitialized in this function The compiler speaketh truth. Cc: Paul Fulghum Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/synclink_gt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 2001b0e..55c1653 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c @@ -916,7 +916,7 @@ static int put_char(struct tty_struct *tty, unsigned char ch) { struct slgt_info *info = tty->driver_data; unsigned long flags; - int ret; + int ret = 0; if (sanity_check(info, tty->name, "put_char")) return 0; -- cgit v1.1 From 417607d05f41dbe2acccdb7a298a81d30ba1d22b Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 12 May 2008 14:02:35 -0700 Subject: RTC/watchdog: M41T80: fix a potential use of unitialized data Watchdog handlers within the driver make use of "save_client" -- make sure it has been initalized before the handlers are registered. Signed-off-by: Maciej W. Rozycki Cc: Alessandro Zummo Cc: Alexander Bigga Cc: Wim Van Sebroeck Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-m41t80.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 316bfaa..3d451ec 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -803,6 +803,7 @@ static int m41t80_probe(struct i2c_client *client, #ifdef CONFIG_RTC_DRV_M41T80_WDT if (clientdata->features & M41T80_FEATURE_HT) { + save_client = client; rc = misc_register(&wdt_dev); if (rc) goto exit; @@ -811,7 +812,6 @@ static int m41t80_probe(struct i2c_client *client, misc_deregister(&wdt_dev); goto exit; } - save_client = client; } #endif return 0; -- cgit v1.1 From 9fb1f68d40d9dd99fdbf65349c9c6af760e19e6e Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Mon, 12 May 2008 14:02:38 -0700 Subject: rtc: m41t80: include for printk() The driver uses printk(), but does not include -- add it. Signed-off-by: Maciej W. Rozycki Cc: Alessandro Zummo Cc: Alexander Bigga Cc: Wim Van Sebroeck Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-m41t80.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/rtc/rtc-m41t80.c b/drivers/rtc/rtc-m41t80.c index 3d451ec..a3e0880 100644 --- a/drivers/rtc/rtc-m41t80.c +++ b/drivers/rtc/rtc-m41t80.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include -- cgit v1.1 From 7fe3915a492503a9199af475a433b50258303806 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 12 May 2008 14:02:38 -0700 Subject: vt/fbcon: update scrl_erase_char after 256/512-glyph font switch Addendum to commit c9e587abfdec2c2aaa55fab83bcb4972e2f84f9b ("vt: fix background color on line feed"). vc->vc_scrl_erase_char was not updated when fbcon switches between 256- and 512-glyph fonts. Signed-off-by: Jan Engelhardt Acked-by: David S. Miller Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index ad31983..b9703c1 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -2507,6 +2507,9 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, c = vc->vc_video_erase_char; vc->vc_video_erase_char = ((c & 0xfe00) >> 1) | (c & 0xff); + c = vc->vc_def_color; + vc->vc_scrl_erase_char = + ((c & 0xFE00) >> 1) | (c & 0xFF); vc->vc_attr >>= 1; } } else if (!vc->vc_hi_font_mask && cnt == 512) { @@ -2537,9 +2540,14 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, if (vc->vc_can_do_color) { vc->vc_video_erase_char = ((c & 0xff00) << 1) | (c & 0xff); + c = vc->vc_def_color; + vc->vc_scrl_erase_char = + ((c & 0xFF00) << 1) | (c & 0xFF); vc->vc_attr <<= 1; - } else + } else { vc->vc_video_erase_char = c & ~0x100; + vc->vc_scrl_erase_char = c & ~0x100; + } } } -- cgit v1.1 From d850a2fac11e4dd45d1d3d493a5a071b06c58c99 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 12 May 2008 14:02:39 -0700 Subject: vt/fbcon: fix background color on line feed Another addendum to commit c9e587abfdec2c2aaa55fab83bcb4972e2f84f9b ("vt: fix background color on line feed"). fbcon still was not doing the right thing (read: continued to do old behavior). fbcon_clear() seems to clear the new line (e.g. where your new prompt appears after doing echo -en "\e[42mfoo\n"), while scr_memsetw clears the previous one only (where "foo" appears). So just temporarily set the video_erase_char to the scrl_erase_char so that fbcon_clear does the right thing. Signed-off-by: Jan Engelhardt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index b9703c1..5fa8b76 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -1853,6 +1853,8 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; struct display *p = &fb_display[vc->vc_num]; int scroll_partial = info->flags & FBINFO_PARTIAL_PAN_OK; + unsigned short saved_ec; + int ret; if (fbcon_is_inactive(vc, info)) return -EINVAL; @@ -1865,6 +1867,11 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, * whole screen (prevents flicker). */ + saved_ec = vc->vc_video_erase_char; + vc->vc_video_erase_char = vc->vc_scrl_erase_char; + + ret = 0; + switch (dir) { case SM_UP: if (count > vc->vc_rows) /* Maximum realistic size */ @@ -1883,7 +1890,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, (b - count)), vc->vc_scrl_erase_char, vc->vc_size_row * count); - return 1; + ret = 1; break; case SCROLL_WRAP_MOVE: @@ -1955,7 +1962,8 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, (b - count)), vc->vc_scrl_erase_char, vc->vc_size_row * count); - return 1; + ret = 1; + break; } break; @@ -1974,7 +1982,7 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, t), vc->vc_scrl_erase_char, vc->vc_size_row * count); - return 1; + ret = 1; break; case SCROLL_WRAP_MOVE: @@ -2044,10 +2052,13 @@ static int fbcon_scroll(struct vc_data *vc, int t, int b, int dir, t), vc->vc_scrl_erase_char, vc->vc_size_row * count); - return 1; + ret = 1; + break; } + break; } - return 0; + vc->vc_video_erase_char = saved_ec; + return ret; } -- cgit v1.1 From 43f14d856f013a4cc63da2c765617c665274338c Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Mon, 12 May 2008 14:02:40 -0700 Subject: eCryptFS: fix imbalanced mutex locking Fix imbalanced calls for mutex lock/unlock on ecryptfs_daemon_hash_mux Revealed by Ingo Molnar: http://lkml.org/lkml/2008/5/7/260 Signed-off-by: Cyrill Gorcunov Cc: Michael Halcrow Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ecryptfs/miscdev.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index 788995e..6560da1 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c @@ -257,12 +257,14 @@ ecryptfs_miscdev_read(struct file *file, char __user *buf, size_t count, mutex_lock(&daemon->mux); if (daemon->flags & ECRYPTFS_DAEMON_ZOMBIE) { rc = 0; + mutex_unlock(&ecryptfs_daemon_hash_mux); printk(KERN_WARNING "%s: Attempt to read from zombified " "daemon\n", __func__); goto out_unlock_daemon; } if (daemon->flags & ECRYPTFS_DAEMON_IN_READ) { rc = 0; + mutex_unlock(&ecryptfs_daemon_hash_mux); goto out_unlock_daemon; } /* This daemon will not go away so long as this flag is set */ -- cgit v1.1 From 21e2b0a5efb3a01de58e7cb630f2eb70894da352 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Thu, 8 May 2008 14:37:25 +0900 Subject: PCI ACPI: fix uninitialized variable in __pci_osc_support_set Fix uninitialized variable in __pci_osc_support_set(). If the ACPI namespace doesn't have any device object corresponding to the specified hid, 'retval' in __pci_osc_support_set() is not changed by the acpi_query_osc() callback. Since 'retval' is not initizlized in the current implementation, the contents of 'retval' is undefined in this case. This causes a mis-handling of ctrlset_buf[OSC_SUPPORT_TYPE] and will cause an unexpected result in the subsequent pci_osc_control_set() call as a result. Signed-off-by: Kenji Kaneshige Signed-off-by: Jesse Barnes --- drivers/pci/pci-acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 72f7476..ddfd756 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -166,7 +166,7 @@ run_osc_out: acpi_status __pci_osc_support_set(u32 flags, const char *hid) { u32 temp; - acpi_status retval; + acpi_status retval = AE_NOT_FOUND; if (!(flags & OSC_SUPPORT_MASKS)) { return AE_TYPE; -- cgit v1.1 From 4a367f3a9dbf2e7ffcee4702203479809236ee6e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 9 May 2008 08:06:55 +0200 Subject: x86/PCI: fix broken ISA DMA Rene Herman reported: > commit 8779f2fc3b84ebb6c5181fb13d702e9944c16069 > > "x86: don't try to allocate from DMA zone at first" > > breaks all of ISA DMA. Or all of ALSA ISA DMA at least. All > ISA soundcards are silent following that commit -- no error > messages, everything appears fine, just silence. That patch is buggy. We had an implicit assumption that dev = NULL for ISA devices that require 24bit DMA. The recent work on x86 dma_alloc_coherent() breaks the ISA DMA buffer allocation, which is represented by "dev = NULL" and requires 24bit DMA implicitly. Bisected-by: Rene Herman Signed-off-by: Takashi Iwai Signed-off-by: Ingo Molnar Signed-off-by: Jesse Barnes --- arch/x86/kernel/pci-dma.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 0c37f16..c5ef1af 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -385,11 +385,13 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, if (dma_alloc_from_coherent_mem(dev, size, dma_handle, &memory)) return memory; - if (!dev) + if (!dev) { dev = &fallback_dev; + gfp |= GFP_DMA; + } dma_mask = dev->coherent_dma_mask; if (dma_mask == 0) - dma_mask = DMA_32BIT_MASK; + dma_mask = (gfp & GFP_DMA) ? DMA_24BIT_MASK : DMA_32BIT_MASK; /* Device not DMA able */ if (dev->dma_mask == NULL) @@ -403,7 +405,7 @@ dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, larger than 16MB and in this case we have a chance of finding fitting memory in the next higher zone first. If not retry with true GFP_DMA. -AK */ - if (dma_mask <= DMA_32BIT_MASK) + if (dma_mask <= DMA_32BIT_MASK && !(gfp & GFP_DMA)) gfp |= GFP_DMA32; #endif -- cgit v1.1 From a5d1c8798309a384c2776e5ff472f8ceb6d9065d Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 12 May 2008 10:48:10 +0800 Subject: ACPI/PCI: handle multiple _OSC There is an IA64 system here which have two pci root bridges with _OSC. One _OSC disables SHPC control bit but the other not. Below patch makes _OSC data per-device instead of one global, otherwise linux takes both root bridges don't support SHPC. Signed-off-by: Shaohua Li Signed-off-by: Jesse Barnes --- drivers/pci/pci-acpi.c | 95 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 66 insertions(+), 29 deletions(-) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index ddfd756..468d13e 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -19,8 +19,31 @@ #include #include "pci.h" -static u32 ctrlset_buf[3] = {0, 0, 0}; -static u32 global_ctrlsets = 0; +struct acpi_osc_data { + acpi_handle handle; + u32 ctrlset_buf[3]; + u32 global_ctrlsets; + struct list_head sibiling; +}; +static LIST_HEAD(acpi_osc_data_list); + +static struct acpi_osc_data *acpi_get_osc_data(acpi_handle handle) +{ + struct acpi_osc_data *data; + + list_for_each_entry(data, &acpi_osc_data_list, sibiling) { + if (data->handle == handle) + return data; + } + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + return NULL; + INIT_LIST_HEAD(&data->sibiling); + data->handle = handle; + list_add_tail(&data->sibiling, &acpi_osc_data_list); + return data; +} + static u8 OSC_UUID[16] = {0x5B, 0x4D, 0xDB, 0x33, 0xF7, 0x1F, 0x1C, 0x40, 0x96, 0x57, 0x74, 0x41, 0xC0, 0x3D, 0xD7, 0x66}; static acpi_status @@ -37,8 +60,21 @@ acpi_query_osc ( union acpi_object *out_obj; u32 osc_dw0; acpi_status *ret_status = (acpi_status *)retval; + struct acpi_osc_data *osc_data = acpi_get_osc_data(handle); + u32 flags = (unsigned long)context, temp; + + if (!osc_data) { + printk(KERN_ERR "acpi osc data array is full\n"); + return AE_ERROR; + } + + osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS); + + /* do _OSC query for all possible controls */ + temp = osc_data->ctrlset_buf[OSC_CONTROL_TYPE]; + osc_data->ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; + osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; - /* Setting up input parameters */ input.count = 4; input.pointer = in_params; @@ -51,13 +87,11 @@ acpi_query_osc ( in_params[2].integer.value = 3; in_params[3].type = ACPI_TYPE_BUFFER; in_params[3].buffer.length = 12; - in_params[3].buffer.pointer = (u8 *)context; + in_params[3].buffer.pointer = (u8 *)osc_data->ctrlset_buf; status = acpi_evaluate_object(handle, "_OSC", &input, &output); - if (ACPI_FAILURE (status)) { - *ret_status = status; - return status; - } + if (ACPI_FAILURE(status)) + goto out_nofree; out_obj = output.pointer; if (out_obj->type != ACPI_TYPE_BUFFER) { @@ -76,7 +110,8 @@ acpi_query_osc ( printk(KERN_DEBUG "_OSC invalid revision\n"); if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { /* Update Global Control Set */ - global_ctrlsets = *((u32 *)(out_obj->buffer.pointer+8)); + osc_data->global_ctrlsets = + *((u32 *)(out_obj->buffer.pointer + 8)); status = AE_OK; goto query_osc_out; } @@ -85,12 +120,21 @@ acpi_query_osc ( } /* Update Global Control Set */ - global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8)); + osc_data->global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8)); status = AE_OK; query_osc_out: kfree(output.pointer); +out_nofree: *ret_status = status; + + osc_data->ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE; + osc_data->ctrlset_buf[OSC_CONTROL_TYPE] = temp; + if (ACPI_FAILURE(status)) { + /* no osc support at all */ + osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] = 0; + } + return status; } @@ -165,28 +209,15 @@ run_osc_out: **/ acpi_status __pci_osc_support_set(u32 flags, const char *hid) { - u32 temp; acpi_status retval = AE_NOT_FOUND; if (!(flags & OSC_SUPPORT_MASKS)) { return AE_TYPE; } - ctrlset_buf[OSC_SUPPORT_TYPE] |= (flags & OSC_SUPPORT_MASKS); - - /* do _OSC query for all possible controls */ - temp = ctrlset_buf[OSC_CONTROL_TYPE]; - ctrlset_buf[OSC_QUERY_TYPE] = OSC_QUERY_ENABLE; - ctrlset_buf[OSC_CONTROL_TYPE] = OSC_CONTROL_MASKS; acpi_get_devices(hid, acpi_query_osc, - ctrlset_buf, + (void *)(unsigned long)flags, (void **) &retval ); - ctrlset_buf[OSC_QUERY_TYPE] = !OSC_QUERY_ENABLE; - ctrlset_buf[OSC_CONTROL_TYPE] = temp; - if (ACPI_FAILURE(retval)) { - /* no osc support at all */ - ctrlset_buf[OSC_SUPPORT_TYPE] = 0; - } return AE_OK; } @@ -201,19 +232,25 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) { acpi_status status; u32 ctrlset; + struct acpi_osc_data *osc_data = acpi_get_osc_data(handle); + + if (!osc_data) { + printk(KERN_ERR "acpi osc data array is full\n"); + return AE_ERROR; + } ctrlset = (flags & OSC_CONTROL_MASKS); if (!ctrlset) { return AE_TYPE; } - if (ctrlset_buf[OSC_SUPPORT_TYPE] && - ((global_ctrlsets & ctrlset) != ctrlset)) { + if (osc_data->ctrlset_buf[OSC_SUPPORT_TYPE] && + ((osc_data->global_ctrlsets & ctrlset) != ctrlset)) { return AE_SUPPORT; } - ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; - status = acpi_run_osc(handle, ctrlset_buf); + osc_data->ctrlset_buf[OSC_CONTROL_TYPE] |= ctrlset; + status = acpi_run_osc(handle, osc_data->ctrlset_buf); if (ACPI_FAILURE (status)) { - ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; + osc_data->ctrlset_buf[OSC_CONTROL_TYPE] &= ~ctrlset; } return status; -- cgit v1.1 From 34a65055e5e7304b3d6ad0f7542bf66308eae50a Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Mon, 12 May 2008 22:55:45 +0900 Subject: ACPI/PCI: handle multiple _OSC The pci_osc_control_set() function can be called for the ACPI object that doesn't have _OSC method. In this case, acpi_get_osc_data() would allocate a useless memory region. To avoid this, we need to check the existence of _OSC before calling acpi_get_osc_data(). Here is a patch to fix this problem in pci_osc_control_set. Signed-off-by: Kenji Kaneshige Signed-off-by: Jesse Barnes --- drivers/pci/pci-acpi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 468d13e..38fc8b1 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -232,8 +232,14 @@ acpi_status pci_osc_control_set(acpi_handle handle, u32 flags) { acpi_status status; u32 ctrlset; - struct acpi_osc_data *osc_data = acpi_get_osc_data(handle); + acpi_handle tmp; + struct acpi_osc_data *osc_data; + + status = acpi_get_handle(handle, "_OSC", &tmp); + if (ACPI_FAILURE(status)) + return status; + osc_data = acpi_get_osc_data(handle); if (!osc_data) { printk(KERN_ERR "acpi osc data array is full\n"); return AE_ERROR; -- cgit v1.1 From a7eb08c2a14f28cb652ea6ad1a8e2b8efc55fb9a Mon Sep 17 00:00:00 2001 From: mark gross Date: Mon, 12 May 2008 13:41:57 -0700 Subject: PCI: Make the intel-iommu_wait_op macro work when jiffies are not running The following patch changes the intel-iommu.c code to use the TSC instead of jiffies for detecting bad DMAR functionality. Some systems with bad bios's have been seen to hang in early boot spinning in the IOMMU_WAIT_IO macro. This patch will replace the infinite loop with a call to panic. Signed-off-by: Mark Gross Signed-off-by: Jesse Barnes --- drivers/pci/intel-iommu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 1fd8bb7..66c0fd2 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -49,7 +49,7 @@ #define DEFAULT_DOMAIN_ADDRESS_WIDTH 48 -#define DMAR_OPERATION_TIMEOUT (HZ*60) /* 1m */ +#define DMAR_OPERATION_TIMEOUT ((cycles_t) tsc_khz*10*1000) /* 10sec */ #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1) @@ -490,12 +490,12 @@ static int iommu_alloc_root_entry(struct intel_iommu *iommu) #define IOMMU_WAIT_OP(iommu, offset, op, cond, sts) \ {\ - unsigned long start_time = jiffies;\ + cycles_t start_time = get_cycles();\ while (1) {\ sts = op (iommu->reg + offset);\ if (cond)\ break;\ - if (time_after(jiffies, start_time + DMAR_OPERATION_TIMEOUT))\ + if (DMAR_OPERATION_TIMEOUT < (get_cycles() - start_time))\ panic("DMAR hardware is malfunctioning\n");\ cpu_relax();\ }\ -- cgit v1.1 From 439a7733e8fcbaee39979c10246101565834d6b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Krombholz?= Date: Mon, 12 May 2008 00:24:27 +0200 Subject: PCI: enable nv_msi_ht_cap_quirk for ALi bridges MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This applies the NVidia MSI enabled flag for HT capable devices quirk to ALi bridges as well. As described in more detail in http://bugzilla.kernel.org/show_bug.cgi?id=10667 this is required for my board which is using an nForce 3 250Gb chipset with an ALi M1695 northbridge. It fixes a regression introduced in 2.6.24 that made the internal NIC of the board unusable (MSI initialisation of the NIC but disabled MSI on the northbridge devices. Signed-off-by: Björn Krombholz Signed-off-by: Jesse Barnes --- drivers/pci/quirks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index afd914e..f2d9c77 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1826,6 +1826,7 @@ static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) } } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, nv_msi_ht_cap_quirk); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AL, PCI_ANY_ID, nv_msi_ht_cap_quirk); static void __devinit quirk_msi_intx_disable_bug(struct pci_dev *dev) { -- cgit v1.1 From 77db9885646f8a88214ea482988d41f8f73630f4 Mon Sep 17 00:00:00 2001 From: Venki Pallipadi Date: Fri, 9 May 2008 13:05:19 -0700 Subject: x86/PCI: X86_PAT & mprotect Some versions of X used the mprotect workaround to change caching type from UC to WB, so that it can then use mtrr to program WC for that region [1]. Change the mmap of pci space through /sys or /proc interfaces from UC to UC_MINUS. With this change, X will not need to use mprotect workaround to get WC type since the MTRR mapping type will be honored. The bug in mprotect that clobbers PAT bits is fixed in a follow on patch. So, this X workaround will stop working as well. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar Signed-off-by: Jesse Barnes --- arch/x86/pci/i386.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c index 8af0f0b..10fb308 100644 --- a/arch/x86/pci/i386.c +++ b/arch/x86/pci/i386.c @@ -301,15 +301,13 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, prot = pgprot_val(vma->vm_page_prot); if (pat_wc_enabled && write_combine) prot |= _PAGE_CACHE_WC; - else if (pat_wc_enabled) + else if (pat_wc_enabled || boot_cpu_data.x86 > 3) /* * ioremap() and ioremap_nocache() defaults to UC MINUS for now. * To avoid attribute conflicts, request UC MINUS here * aswell. */ prot |= _PAGE_CACHE_UC_MINUS; - else if (boot_cpu_data.x86 > 3) - prot |= _PAGE_CACHE_UC; vma->vm_page_prot = __pgprot(prot); -- cgit v1.1 From c4e5fadd2a6fc0da465dcde761877d9a87313b33 Mon Sep 17 00:00:00 2001 From: Kenji Kaneshige Date: Tue, 13 May 2008 16:48:50 +0900 Subject: ACPI/PCI: another multiple _OSC memory leak fix The acpi_query_osc() function can be called for the ACPI object that doesn't have _OSC method. In this case, acpi_get_osc_data() would allocate a useless memory region. To avoid this, we need to check the existence of _OSC before calling acpi_get_osc_data() in acpi_query_osc(). Signed-off-by: Kenji Kaneshige Signed-off-by: Jesse Barnes --- drivers/pci/pci-acpi.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 38fc8b1..9d6fc8e 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -60,9 +60,15 @@ acpi_query_osc ( union acpi_object *out_obj; u32 osc_dw0; acpi_status *ret_status = (acpi_status *)retval; - struct acpi_osc_data *osc_data = acpi_get_osc_data(handle); + struct acpi_osc_data *osc_data; u32 flags = (unsigned long)context, temp; + acpi_handle tmp; + status = acpi_get_handle(handle, "_OSC", &tmp); + if (ACPI_FAILURE(status)) + return status; + + osc_data = acpi_get_osc_data(handle); if (!osc_data) { printk(KERN_ERR "acpi osc data array is full\n"); return AE_ERROR; -- cgit v1.1 From af5741c6de4f4a1d8608b0f00867c77cb7123635 Mon Sep 17 00:00:00 2001 From: Jeremy Higdon Date: Sun, 11 May 2008 23:17:03 -0700 Subject: [SCSI] qla1280: Fix queue depth problem The qla1280 driver was ANDing the output value of mailbox register 0 with (1 << target-number) to determine whether to enable queueing on the target in question. But mailbox register 0 has the status code for the mailbox command (in this case, Set Target Parameters). Potential values are: /* * ISP mailbox command complete status codes */ So clearly that is in error. I can't think what the author of that line was looking for in a mailbox register, so I just eliminated the AND. flag is used later in the function, and I think that the later usage was also wrong, though it was used to set values that aren't used. Oh well, an overhaul of this driver is not what I want to do now -- just a bugfix. After the fix, I found that my disks were getting a queue depth of 255, which is far too many. Most SCSI disks are limited to 32 or 64. In any case, there's no point, queueing up a bunch of commands to the adapter that will just result in queue full or starve other targets from being issued commands due to running out of internal memory. So I dropped default queue depth to 32 (from which 1 is subtracted elsewhere, giving net of 31). I tested with a Seagate ST336753LC, and results look good, so I'm satisfied with this patch. Signed-off-by: Jeremy Higdon Acked-by: Jes Sorensen Cc: Stable Tree Signed-off-by: James Bottomley --- drivers/scsi/qla1280.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index fa06093..51e2f29 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -2007,7 +2007,7 @@ qla1280_set_defaults(struct scsi_qla_host *ha) nv->bus[bus].config_2.req_ack_active_negation = 1; nv->bus[bus].config_2.data_line_active_negation = 1; nv->bus[bus].selection_timeout = 250; - nv->bus[bus].max_queue_depth = 256; + nv->bus[bus].max_queue_depth = 32; if (IS_ISP1040(ha)) { nv->bus[bus].bus_reset_delay = 3; @@ -2051,7 +2051,7 @@ qla1280_config_target(struct scsi_qla_host *ha, int bus, int target) status = qla1280_mailbox_command(ha, 0x0f, mb); /* Save Tag queuing enable flag. */ - flag = (BIT_0 << target) & mb[0]; + flag = (BIT_0 << target); if (nv->bus[bus].target[target].parameter.tag_queuing) ha->bus_settings[bus].qtag_enables |= flag; -- cgit v1.1 From 61165d7a035f6571c7576e7f51e7230157724c8d Mon Sep 17 00:00:00 2001 From: Hugh Dickins Date: Tue, 13 May 2008 14:26:57 +0100 Subject: x86: fix app crashes after SMP resume After resume on a 2cpu laptop, kernel builds collapse with a sed hang, sh or make segfault (often on 20295564), real-time signal to cc1 etc. Several hurdles to jump, but a manually-assisted bisect led to -rc1's d2bcbad5f3ad38a1c09861bca7e252dde7bb8259 x86: do not zap_low_mappings in __smp_prepare_cpus. Though the low mappings were removed at bootup, they were left behind (with Global flags helping to keep them in TLB) after resume or cpu online, causing the crashes seen. Reinstate zap_low_mappings (with local __flush_tlb_all) for each cpu_up on x86_32. This used to be serialized by smp_commenced_mask: that's now gone, but a low_mappings flag will do. No need for native_smp_cpus_done to repeat the zap: let mem_init zap BSP's low mappings just like on UP. (In passing, fix error code from native_cpu_up: do_boot_cpu returns a variety of diagnostic values, Dprintk what it says but convert to -EIO. And save_pg_dir separately before zap_low_mappings: doesn't matter now, but zapping twice in succession wiped out resume's swsusp_pg_dir.) That worked well on the duo and one quad, but wouldn't boot 3rd or 4th cpu on P4 Xeon, oopsing just after unlock_ipi_call_lock. The TLB flush IPI now being sent reveals a long-standing bug: the booting cpu has its APIC readied in smp_callin at the top of start_secondary, but isn't put into the cpu_online_map until just before that unlock_ipi_call_lock. So native_smp_call_function_mask to online cpus would send_IPI_allbutself, including the cpu just coming up, though it has been excluded from the count to wait for: by the time it handles the IPI, the call data on native_smp_call_function_mask's stack may well have been overwritten. So fall back to send_IPI_mask while cpu_online_map does not match cpu_callout_map: perhaps there's a better APICological fix to be made at the start_secondary end, but I wouldn't know that. Signed-off-by: Hugh Dickins Signed-off-by: Ingo Molnar --- arch/x86/kernel/smp.c | 3 ++- arch/x86/kernel/smpboot.c | 24 +++++++++++++++++------- arch/x86/mm/init_32.c | 12 +----------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index 8f75893..0cb7aad 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c @@ -231,7 +231,8 @@ native_smp_call_function_mask(cpumask_t mask, wmb(); /* Send a message to other CPUs */ - if (cpus_equal(mask, allbutself)) + if (cpus_equal(mask, allbutself) && + cpus_equal(cpu_online_map, cpu_callout_map)) send_IPI_allbutself(CALL_FUNCTION_VECTOR); else send_IPI_mask(mask, CALL_FUNCTION_VECTOR); diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 6b087ab..3898849 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -86,6 +86,7 @@ void *x86_bios_cpu_apicid_early_ptr; #ifdef CONFIG_X86_32 u8 apicid_2_node[MAX_APICID]; +static int low_mappings; #endif /* State of each CPU */ @@ -326,6 +327,12 @@ static void __cpuinit start_secondary(void *unused) enable_8259A_irq(0); } +#ifdef CONFIG_X86_32 + while (low_mappings) + cpu_relax(); + __flush_tlb_all(); +#endif + /* This must be done before setting cpu_online_map */ set_cpu_sibling_map(raw_smp_processor_id()); wmb(); @@ -1040,14 +1047,20 @@ int __cpuinit native_cpu_up(unsigned int cpu) #ifdef CONFIG_X86_32 /* init low mem mapping */ clone_pgd_range(swapper_pg_dir, swapper_pg_dir + KERNEL_PGD_BOUNDARY, - min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY)); + min_t(unsigned long, KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY)); flush_tlb_all(); -#endif + low_mappings = 1; err = do_boot_cpu(apicid, cpu); - if (err < 0) { + + zap_low_mappings(); + low_mappings = 0; +#else + err = do_boot_cpu(apicid, cpu); +#endif + if (err) { Dprintk("do_boot_cpu failed %d\n", err); - return err; + return -EIO; } /* @@ -1259,9 +1272,6 @@ void __init native_smp_cpus_done(unsigned int max_cpus) setup_ioapic_dest(); #endif check_nmi_watchdog(); -#ifdef CONFIG_X86_32 - zap_low_mappings(); -#endif } #ifdef CONFIG_HOTPLUG_CPU diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c index de236e4..ec30d10 100644 --- a/arch/x86/mm/init_32.c +++ b/arch/x86/mm/init_32.c @@ -438,8 +438,6 @@ void zap_low_mappings(void) { int i; - save_pg_dir(); - /* * Zap initial low-memory mappings. * @@ -663,16 +661,8 @@ void __init mem_init(void) test_wp_bit(); cpa_init(); - - /* - * Subtle. SMP is doing it's boot stuff late (because it has to - * fork idle threads) - but it also needs low mappings for the - * protected-mode entry to work. We zap these entries only after - * the WP-bit has been tested. - */ -#ifndef CONFIG_SMP + save_pg_dir(); zap_low_mappings(); -#endif } #ifdef CONFIG_MEMORY_HOTPLUG -- cgit v1.1 From 8c45a4e4f2b9bed6b6c54aaafc89e906284ccdf2 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 12 May 2008 19:31:20 -0700 Subject: x86: early_init_centaur(): use set_cpu_cap() arch/x86/kernel/setup_64.c:954: warning: passing argument 2 of 'set_bit' from incompatible pointer type Signed-off-by: Andrew Morton Signed-off-by: Ingo Molnar --- arch/x86/kernel/setup_64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index f2fc8fe..6dff128 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -951,7 +951,7 @@ static void __cpuinit init_intel(struct cpuinfo_x86 *c) static void __cpuinit early_init_centaur(struct cpuinfo_x86 *c) { if (c->x86 == 0x6 && c->x86_model >= 0xf) - set_bit(X86_FEATURE_CONSTANT_TSC, &c->x86_capability); + set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC); } static void __cpuinit init_centaur(struct cpuinfo_x86 *c) -- cgit v1.1 From 89804c022fe32541f5dd40a69e48ff4678d9ad24 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 13 May 2008 10:36:22 +0200 Subject: x86: fix csum_partial() export Fix this symbol export problem: Building modules, stage 2. MODPOST 193 modules ERROR: "csum_partial" [fs/reiserfs/reiserfs.ko] undefined! make[1]: *** [__modpost] Error 1 make: *** [modules] Error 2 This is due to a known weakness of symbol exports: if a symbol's only in-core user is an EXPORT_SYMBOL from a lib-y section, the symbol is not linked in. The solution is to move the export to x8664_ksyms_64.c - but the real solution would be to fix kbuild. Signed-off-by: Ingo Molnar --- arch/x86/kernel/x8664_ksyms_64.c | 3 +++ arch/x86/lib/csum-partial_64.c | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/x8664_ksyms_64.c b/arch/x86/kernel/x8664_ksyms_64.c index 58882f9..f6c05d0 100644 --- a/arch/x86/kernel/x8664_ksyms_64.c +++ b/arch/x86/kernel/x8664_ksyms_64.c @@ -2,6 +2,7 @@ All C exports should go in the respective C files. */ #include +#include #include #include @@ -29,6 +30,8 @@ EXPORT_SYMBOL(__copy_from_user_inatomic); EXPORT_SYMBOL(copy_page); EXPORT_SYMBOL(clear_page); +EXPORT_SYMBOL(csum_partial); + /* * Export string functions. We normally rely on gcc builtin for most of these, * but gcc sometimes decides not to inline them. diff --git a/arch/x86/lib/csum-partial_64.c b/arch/x86/lib/csum-partial_64.c index bc503f5..bf51144 100644 --- a/arch/x86/lib/csum-partial_64.c +++ b/arch/x86/lib/csum-partial_64.c @@ -136,8 +136,6 @@ __wsum csum_partial(const void *buff, int len, __wsum sum) (__force u32)sum); } -EXPORT_SYMBOL(csum_partial); - /* * this routine is used for miscellaneous IP-like checksums, mainly * in icmp.c -- cgit v1.1 From afc85343807bc2c488b7372cd7547875dfe03fe5 Mon Sep 17 00:00:00 2001 From: Pranith Kumar Date: Mon, 12 May 2008 14:52:26 +0530 Subject: x86: arch/x86/mm/pat.c - fix warning fix this warning: arch/x86/mm/pat.c: In function `phys_mem_access_prot_allowed': arch/x86/mm/pat.c:558: warning: long long unsigned int format, long unsigned int arg (arg 6) arch/x86/mm/pat.c: In function `map_devmem': arch/x86/mm/pat.c:580: warning: long long unsigned int format, long unsigned int arg (arg 6) Signed-off-by: D Pranith Kumar Signed-off-by: Ingo Molnar --- arch/x86/mm/pat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/mm/pat.c b/arch/x86/mm/pat.c index 60adbe2..bcb1a8e 100644 --- a/arch/x86/mm/pat.c +++ b/arch/x86/mm/pat.c @@ -555,7 +555,7 @@ int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, "%s:%d /dev/mem ioremap_change_attr failed %s for %Lx-%Lx\n", current->comm, current->pid, cattr_name(flags), - offset, offset + size); + offset, (unsigned long long)(offset + size)); return 0; } @@ -576,7 +576,7 @@ void map_devmem(unsigned long pfn, unsigned long size, pgprot_t vma_prot) "%s:%d /dev/mem expected mapping type %s for %Lx-%Lx, got %s\n", current->comm, current->pid, cattr_name(want_flags), - addr, addr + size, + addr, (unsigned long long)(addr + size), cattr_name(flags)); } } -- cgit v1.1 From 1f465f4e475454b8bb590846c50a9d16e8046f3d Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Fri, 9 May 2008 15:43:44 -0700 Subject: x86: user_regset_view table fix for ia32 on 64-bit The user_regset_view table for the 32-bit regsets on the 64-bit build had the wrong sizes for the FP regsets. This bug had no user-visible effect (just on kernel modules using the user_regset interfaces and the like). But the fix is trivial and risk-free. Signed-off-by: Roland McGrath Signed-off-by: Ingo Molnar --- arch/x86/kernel/ptrace.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index fb03ef3..a7835f2 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c @@ -1303,6 +1303,9 @@ static const struct user_regset_view user_x86_64_view = { #define genregs32_get genregs_get #define genregs32_set genregs_set +#define user_i387_ia32_struct user_i387_struct +#define user32_fxsr_struct user_fxsr_struct + #endif /* CONFIG_X86_64 */ #if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION @@ -1315,13 +1318,13 @@ static const struct user_regset x86_32_regsets[] = { }, [REGSET_FP] = { .core_note_type = NT_PRFPREG, - .n = sizeof(struct user_i387_struct) / sizeof(u32), + .n = sizeof(struct user_i387_ia32_struct) / sizeof(u32), .size = sizeof(u32), .align = sizeof(u32), .active = fpregs_active, .get = fpregs_get, .set = fpregs_set }, [REGSET_XFP] = { .core_note_type = NT_PRXFPREG, - .n = sizeof(struct user_i387_struct) / sizeof(u32), + .n = sizeof(struct user32_fxsr_struct) / sizeof(u32), .size = sizeof(u32), .align = sizeof(u32), .active = xfpregs_active, .get = xfpregs_get, .set = xfpregs_set }, -- cgit v1.1 From dd37818dbdf8e51d0288c0197c351c005ffcdbdb Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 13 May 2008 11:27:25 -0700 Subject: RDMA/nes: Fix up nes_lro_max_aggr module parameter Fix some bugs with the max_aggr module parameter added with LRO support: - The module parameter value ignored and not actually used to set lro_mgr.max_aggr. - MODULE_PARM_DESC had a typo "_mro_" instead of "_lro_" so it didn't end up describing the actual module parameter. - The nes_lro_max_aggr variable was declared as unsigned, but the module_param line said "int" instead of "uint" for the type. - The default value for the parameter was stuck in the permissions field of module_param, which led to nonsensical permissions for the file under /sys/module/iw_nes/param. - The parameter was used in only one file but defined in another, which led to the variable being global for no good reason. Move everything related to the parameter to the file nes_hw.c where it is actually used. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/nes/nes.c | 4 ---- drivers/infiniband/hw/nes/nes.h | 1 - drivers/infiniband/hw/nes/nes_hw.c | 6 +++++- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/hw/nes/nes.c b/drivers/infiniband/hw/nes/nes.c index 9f7364a..a4e9269 100644 --- a/drivers/infiniband/hw/nes/nes.c +++ b/drivers/infiniband/hw/nes/nes.c @@ -91,10 +91,6 @@ unsigned int nes_debug_level = 0; module_param_named(debug_level, nes_debug_level, uint, 0644); MODULE_PARM_DESC(debug_level, "Enable debug output level"); -unsigned int nes_lro_max_aggr = NES_LRO_MAX_AGGR; -module_param(nes_lro_max_aggr, int, NES_LRO_MAX_AGGR); -MODULE_PARM_DESC(nes_mro_max_aggr, " nic LRO MAX packet aggregation"); - LIST_HEAD(nes_adapter_list); static LIST_HEAD(nes_dev_list); diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index 1f9f7bf..61b46e9 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h @@ -173,7 +173,6 @@ extern int disable_mpa_crc; extern unsigned int send_first; extern unsigned int nes_drv_opt; extern unsigned int nes_debug_level; -extern unsigned int nes_lro_max_aggr; extern struct list_head nes_adapter_list; diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index 8dc70f9..d3278f1 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -42,6 +42,10 @@ #include "nes.h" +static unsigned int nes_lro_max_aggr = NES_LRO_MAX_AGGR; +module_param(nes_lro_max_aggr, uint, 0444); +MODULE_PARM_DESC(nes_lro_max_aggr, "NIC LRO max packet aggregation"); + static u32 crit_err_count; u32 int_mod_timer_init; u32 int_mod_cq_depth_256; @@ -1738,7 +1742,7 @@ int nes_init_nic_qp(struct nes_device *nesdev, struct net_device *netdev) jumbomode = 1; nes_nic_init_timer_defaults(nesdev, jumbomode); } - nesvnic->lro_mgr.max_aggr = NES_LRO_MAX_AGGR; + nesvnic->lro_mgr.max_aggr = nes_lro_max_aggr; nesvnic->lro_mgr.max_desc = NES_MAX_LRO_DESCRIPTORS; nesvnic->lro_mgr.lro_arr = nesvnic->lro_desc; nesvnic->lro_mgr.get_skb_header = nes_lro_get_skb_hdr; -- cgit v1.1 From 53dc1ca194c062aa9771e194047f27ec1ca592df Mon Sep 17 00:00:00 2001 From: Ralph Campbell Date: Tue, 13 May 2008 11:40:25 -0700 Subject: IB/ipath: Fix RC and UC error handling When errors are detected in RC, the QP should transition to the IB_QPS_ERR state, not the IB_QPS_SQE state. Also, when the error is on the responder side, the receive work completion error was incorrect (remote vs. local). Signed-off-by: Ralph Campbell Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_qp.c | 54 ++-------- drivers/infiniband/hw/ipath/ipath_rc.c | 127 ++++++++--------------- drivers/infiniband/hw/ipath/ipath_ruc.c | 165 ++++++++++++++---------------- drivers/infiniband/hw/ipath/ipath_verbs.c | 4 +- drivers/infiniband/hw/ipath/ipath_verbs.h | 6 +- 5 files changed, 132 insertions(+), 224 deletions(-) diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c index dd5b6e9..6f98632 100644 --- a/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/drivers/infiniband/hw/ipath/ipath_qp.c @@ -374,13 +374,14 @@ static void ipath_reset_qp(struct ipath_qp *qp, enum ib_qp_type type) } /** - * ipath_error_qp - put a QP into an error state - * @qp: the QP to put into an error state + * ipath_error_qp - put a QP into the error state + * @qp: the QP to put into the error state * @err: the receive completion error to signal if a RWQE is active * * Flushes both send and receive work queues. * Returns true if last WQE event should be generated. * The QP s_lock should be held and interrupts disabled. + * If we are already in error state, just return. */ int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err) @@ -389,8 +390,10 @@ int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err) struct ib_wc wc; int ret = 0; - ipath_dbg("QP%d/%d in error state (%d)\n", - qp->ibqp.qp_num, qp->remote_qpn, err); + if (qp->state == IB_QPS_ERR) + goto bail; + + qp->state = IB_QPS_ERR; spin_lock(&dev->pending_lock); if (!list_empty(&qp->timerwait)) @@ -460,6 +463,7 @@ int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err) } else if (qp->ibqp.event_handler) ret = 1; +bail: return ret; } @@ -1026,48 +1030,6 @@ bail: } /** - * ipath_sqerror_qp - put a QP's send queue into an error state - * @qp: QP who's send queue will be put into an error state - * @wc: the WC responsible for putting the QP in this state - * - * Flushes the send work queue. - * The QP s_lock should be held and interrupts disabled. - */ - -void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc) -{ - struct ipath_ibdev *dev = to_idev(qp->ibqp.device); - struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last); - - ipath_dbg("Send queue error on QP%d/%d: err: %d\n", - qp->ibqp.qp_num, qp->remote_qpn, wc->status); - - spin_lock(&dev->pending_lock); - if (!list_empty(&qp->timerwait)) - list_del_init(&qp->timerwait); - if (!list_empty(&qp->piowait)) - list_del_init(&qp->piowait); - spin_unlock(&dev->pending_lock); - - ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 1); - if (++qp->s_last >= qp->s_size) - qp->s_last = 0; - - wc->status = IB_WC_WR_FLUSH_ERR; - - while (qp->s_last != qp->s_head) { - wqe = get_swqe_ptr(qp, qp->s_last); - wc->wr_id = wqe->wr.wr_id; - wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; - ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 1); - if (++qp->s_last >= qp->s_size) - qp->s_last = 0; - } - qp->s_cur = qp->s_tail = qp->s_head; - qp->state = IB_QPS_SQE; -} - -/** * ipath_get_credit - flush the send work queue of a QP * @qp: the qp who's send work queue to flush * @aeth: the Acknowledge Extended Transport Header diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index 08b11b5..b4b26c3 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c @@ -771,27 +771,14 @@ done: * * The QP s_lock should be held and interrupts disabled. */ -void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc) +void ipath_restart_rc(struct ipath_qp *qp, u32 psn) { struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last); struct ipath_ibdev *dev; if (qp->s_retry == 0) { - wc->wr_id = wqe->wr.wr_id; - wc->status = IB_WC_RETRY_EXC_ERR; - wc->opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; - wc->vendor_err = 0; - wc->byte_len = 0; - wc->qp = &qp->ibqp; - wc->imm_data = 0; - wc->src_qp = qp->remote_qpn; - wc->wc_flags = 0; - wc->pkey_index = 0; - wc->slid = qp->remote_ah_attr.dlid; - wc->sl = qp->remote_ah_attr.sl; - wc->dlid_path_bits = 0; - wc->port_num = 0; - ipath_sqerror_qp(qp, wc); + ipath_send_complete(qp, wqe, IB_WC_RETRY_EXC_ERR); + ipath_error_qp(qp, IB_WC_WR_FLUSH_ERR); goto bail; } qp->s_retry--; @@ -804,6 +791,8 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc) spin_lock(&dev->pending_lock); if (!list_empty(&qp->timerwait)) list_del_init(&qp->timerwait); + if (!list_empty(&qp->piowait)) + list_del_init(&qp->piowait); spin_unlock(&dev->pending_lock); if (wqe->wr.opcode == IB_WR_RDMA_READ) @@ -845,6 +834,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, { struct ipath_ibdev *dev = to_idev(qp->ibqp.device); struct ib_wc wc; + enum ib_wc_status status; struct ipath_swqe *wqe; int ret = 0; u32 ack_psn; @@ -909,7 +899,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, */ update_last_psn(qp, wqe->psn - 1); /* Retry this request. */ - ipath_restart_rc(qp, wqe->psn, &wc); + ipath_restart_rc(qp, wqe->psn); /* * No need to process the ACK/NAK since we are * restarting an earlier request. @@ -937,20 +927,15 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, /* Post a send completion queue entry if requested. */ if (!(qp->s_flags & IPATH_S_SIGNAL_REQ_WR) || (wqe->wr.send_flags & IB_SEND_SIGNALED)) { + memset(&wc, 0, sizeof wc); wc.wr_id = wqe->wr.wr_id; wc.status = IB_WC_SUCCESS; wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; - wc.vendor_err = 0; wc.byte_len = wqe->length; - wc.imm_data = 0; wc.qp = &qp->ibqp; wc.src_qp = qp->remote_qpn; - wc.wc_flags = 0; - wc.pkey_index = 0; wc.slid = qp->remote_ah_attr.dlid; wc.sl = qp->remote_ah_attr.sl; - wc.dlid_path_bits = 0; - wc.port_num = 0; ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 0); } qp->s_retry = qp->s_retry_cnt; @@ -1012,7 +997,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, if (qp->s_last == qp->s_tail) goto bail; if (qp->s_rnr_retry == 0) { - wc.status = IB_WC_RNR_RETRY_EXC_ERR; + status = IB_WC_RNR_RETRY_EXC_ERR; goto class_b; } if (qp->s_rnr_retry_cnt < 7) @@ -1050,37 +1035,25 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, * RDMA READ response which terminates the RDMA * READ. */ - ipath_restart_rc(qp, psn, &wc); + ipath_restart_rc(qp, psn); break; case 1: /* Invalid Request */ - wc.status = IB_WC_REM_INV_REQ_ERR; + status = IB_WC_REM_INV_REQ_ERR; dev->n_other_naks++; goto class_b; case 2: /* Remote Access Error */ - wc.status = IB_WC_REM_ACCESS_ERR; + status = IB_WC_REM_ACCESS_ERR; dev->n_other_naks++; goto class_b; case 3: /* Remote Operation Error */ - wc.status = IB_WC_REM_OP_ERR; + status = IB_WC_REM_OP_ERR; dev->n_other_naks++; class_b: - wc.wr_id = wqe->wr.wr_id; - wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; - wc.vendor_err = 0; - wc.byte_len = 0; - wc.qp = &qp->ibqp; - wc.imm_data = 0; - wc.src_qp = qp->remote_qpn; - wc.wc_flags = 0; - wc.pkey_index = 0; - wc.slid = qp->remote_ah_attr.dlid; - wc.sl = qp->remote_ah_attr.sl; - wc.dlid_path_bits = 0; - wc.port_num = 0; - ipath_sqerror_qp(qp, &wc); + ipath_send_complete(qp, wqe, status); + ipath_error_qp(qp, IB_WC_WR_FLUSH_ERR); break; default: @@ -1126,8 +1099,8 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, int header_in_data) { struct ipath_swqe *wqe; + enum ib_wc_status status; unsigned long flags; - struct ib_wc wc; int diff; u32 pad; u32 aeth; @@ -1159,6 +1132,7 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, if (unlikely(qp->s_last == qp->s_tail)) goto ack_done; wqe = get_swqe_ptr(qp, qp->s_last); + status = IB_WC_SUCCESS; switch (opcode) { case OP(ACKNOWLEDGE): @@ -1200,7 +1174,7 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, /* no AETH, no ACK */ if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) { dev->n_rdma_seq++; - ipath_restart_rc(qp, qp->s_last_psn + 1, &wc); + ipath_restart_rc(qp, qp->s_last_psn + 1); goto ack_done; } if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) @@ -1261,7 +1235,7 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, /* ACKs READ req. */ if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) { dev->n_rdma_seq++; - ipath_restart_rc(qp, qp->s_last_psn + 1, &wc); + ipath_restart_rc(qp, qp->s_last_psn + 1); goto ack_done; } if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) @@ -1291,31 +1265,16 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, goto ack_done; } -ack_done: - spin_unlock_irqrestore(&qp->s_lock, flags); - goto bail; - ack_op_err: - wc.status = IB_WC_LOC_QP_OP_ERR; + status = IB_WC_LOC_QP_OP_ERR; goto ack_err; ack_len_err: - wc.status = IB_WC_LOC_LEN_ERR; + status = IB_WC_LOC_LEN_ERR; ack_err: - wc.wr_id = wqe->wr.wr_id; - wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; - wc.vendor_err = 0; - wc.byte_len = 0; - wc.imm_data = 0; - wc.qp = &qp->ibqp; - wc.src_qp = qp->remote_qpn; - wc.wc_flags = 0; - wc.pkey_index = 0; - wc.slid = qp->remote_ah_attr.dlid; - wc.sl = qp->remote_ah_attr.sl; - wc.dlid_path_bits = 0; - wc.port_num = 0; - ipath_sqerror_qp(qp, &wc); + ipath_send_complete(qp, wqe, status); + ipath_error_qp(qp, IB_WC_WR_FLUSH_ERR); +ack_done: spin_unlock_irqrestore(&qp->s_lock, flags); bail: return; @@ -1523,13 +1482,12 @@ send_ack: return 0; } -static void ipath_rc_error(struct ipath_qp *qp, enum ib_wc_status err) +void ipath_rc_error(struct ipath_qp *qp, enum ib_wc_status err) { unsigned long flags; int lastwqe; spin_lock_irqsave(&qp->s_lock, flags); - qp->state = IB_QPS_ERR; lastwqe = ipath_error_qp(qp, err); spin_unlock_irqrestore(&qp->s_lock, flags); @@ -1643,11 +1601,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, opcode == OP(SEND_LAST) || opcode == OP(SEND_LAST_WITH_IMMEDIATE)) break; - nack_inv: - ipath_rc_error(qp, IB_WC_REM_INV_REQ_ERR); - qp->r_nak_state = IB_NAK_INVALID_REQUEST; - qp->r_ack_psn = qp->r_psn; - goto send_ack; + goto nack_inv; case OP(RDMA_WRITE_FIRST): case OP(RDMA_WRITE_MIDDLE): @@ -1673,18 +1627,13 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, break; } - wc.imm_data = 0; - wc.wc_flags = 0; + memset(&wc, 0, sizeof wc); /* OK, process the packet. */ switch (opcode) { case OP(SEND_FIRST): - if (!ipath_get_rwqe(qp, 0)) { - rnr_nak: - qp->r_nak_state = IB_RNR_NAK | qp->r_min_rnr_timer; - qp->r_ack_psn = qp->r_psn; - goto send_ack; - } + if (!ipath_get_rwqe(qp, 0)) + goto rnr_nak; qp->r_rcv_len = 0; /* FALLTHROUGH */ case OP(SEND_MIDDLE): @@ -1751,14 +1700,10 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, wc.opcode = IB_WC_RECV_RDMA_WITH_IMM; else wc.opcode = IB_WC_RECV; - wc.vendor_err = 0; wc.qp = &qp->ibqp; wc.src_qp = qp->remote_qpn; - wc.pkey_index = 0; wc.slid = qp->remote_ah_attr.dlid; wc.sl = qp->remote_ah_attr.sl; - wc.dlid_path_bits = 0; - wc.port_num = 0; /* Signal completion event if the solicited bit is set. */ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, (ohdr->bth[0] & @@ -1951,11 +1896,21 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, goto send_ack; goto done; +rnr_nak: + qp->r_nak_state = IB_RNR_NAK | qp->r_min_rnr_timer; + qp->r_ack_psn = qp->r_psn; + goto send_ack; + +nack_inv: + ipath_rc_error(qp, IB_WC_LOC_QP_OP_ERR); + qp->r_nak_state = IB_NAK_INVALID_REQUEST; + qp->r_ack_psn = qp->r_psn; + goto send_ack; + nack_acc: - ipath_rc_error(qp, IB_WC_REM_ACCESS_ERR); + ipath_rc_error(qp, IB_WC_LOC_PROT_ERR); qp->r_nak_state = IB_NAK_REMOTE_ACCESS_ERROR; qp->r_ack_psn = qp->r_psn; - send_ack: send_rc_ack(qp); diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c index 9e3fe61..c716a03 100644 --- a/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/drivers/infiniband/hw/ipath/ipath_ruc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. + * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. * * This software is available to you under a choice of one of two @@ -140,20 +140,11 @@ int ipath_init_sge(struct ipath_qp *qp, struct ipath_rwqe *wqe, goto bail; bad_lkey: + memset(&wc, 0, sizeof(wc)); wc.wr_id = wqe->wr_id; wc.status = IB_WC_LOC_PROT_ERR; wc.opcode = IB_WC_RECV; - wc.vendor_err = 0; - wc.byte_len = 0; - wc.imm_data = 0; wc.qp = &qp->ibqp; - wc.src_qp = 0; - wc.wc_flags = 0; - wc.pkey_index = 0; - wc.slid = 0; - wc.sl = 0; - wc.dlid_path_bits = 0; - wc.port_num = 0; /* Signal solicited completion event. */ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1); ret = 0; @@ -270,6 +261,7 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp) struct ib_wc wc; u64 sdata; atomic64_t *maddr; + enum ib_wc_status send_status; qp = ipath_lookup_qpn(&dev->qp_table, sqp->remote_qpn); if (!qp) { @@ -300,8 +292,8 @@ again: wqe = get_swqe_ptr(sqp, sqp->s_last); spin_unlock_irqrestore(&sqp->s_lock, flags); - wc.wc_flags = 0; - wc.imm_data = 0; + memset(&wc, 0, sizeof wc); + send_status = IB_WC_SUCCESS; sqp->s_sge.sge = wqe->sg_list[0]; sqp->s_sge.sg_list = wqe->sg_list + 1; @@ -313,75 +305,33 @@ again: wc.imm_data = wqe->wr.ex.imm_data; /* FALLTHROUGH */ case IB_WR_SEND: - if (!ipath_get_rwqe(qp, 0)) { - rnr_nak: - /* Handle RNR NAK */ - if (qp->ibqp.qp_type == IB_QPT_UC) - goto send_comp; - if (sqp->s_rnr_retry == 0) { - wc.status = IB_WC_RNR_RETRY_EXC_ERR; - goto err; - } - if (sqp->s_rnr_retry_cnt < 7) - sqp->s_rnr_retry--; - dev->n_rnr_naks++; - sqp->s_rnr_timeout = - ib_ipath_rnr_table[qp->r_min_rnr_timer]; - ipath_insert_rnr_queue(sqp); - goto done; - } + if (!ipath_get_rwqe(qp, 0)) + goto rnr_nak; break; case IB_WR_RDMA_WRITE_WITH_IMM: - if (unlikely(!(qp->qp_access_flags & - IB_ACCESS_REMOTE_WRITE))) { - wc.status = IB_WC_REM_INV_REQ_ERR; - goto err; - } + if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_WRITE))) + goto inv_err; wc.wc_flags = IB_WC_WITH_IMM; wc.imm_data = wqe->wr.ex.imm_data; if (!ipath_get_rwqe(qp, 1)) goto rnr_nak; /* FALLTHROUGH */ case IB_WR_RDMA_WRITE: - if (unlikely(!(qp->qp_access_flags & - IB_ACCESS_REMOTE_WRITE))) { - wc.status = IB_WC_REM_INV_REQ_ERR; - goto err; - } + if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_WRITE))) + goto inv_err; if (wqe->length == 0) break; if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, wqe->length, wqe->wr.wr.rdma.remote_addr, wqe->wr.wr.rdma.rkey, - IB_ACCESS_REMOTE_WRITE))) { - acc_err: - wc.status = IB_WC_REM_ACCESS_ERR; - err: - wc.wr_id = wqe->wr.wr_id; - wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; - wc.vendor_err = 0; - wc.byte_len = 0; - wc.qp = &sqp->ibqp; - wc.src_qp = sqp->remote_qpn; - wc.pkey_index = 0; - wc.slid = sqp->remote_ah_attr.dlid; - wc.sl = sqp->remote_ah_attr.sl; - wc.dlid_path_bits = 0; - wc.port_num = 0; - spin_lock_irqsave(&sqp->s_lock, flags); - ipath_sqerror_qp(sqp, &wc); - spin_unlock_irqrestore(&sqp->s_lock, flags); - goto done; - } + IB_ACCESS_REMOTE_WRITE))) + goto acc_err; break; case IB_WR_RDMA_READ: - if (unlikely(!(qp->qp_access_flags & - IB_ACCESS_REMOTE_READ))) { - wc.status = IB_WC_REM_INV_REQ_ERR; - goto err; - } + if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_READ))) + goto inv_err; if (unlikely(!ipath_rkey_ok(qp, &sqp->s_sge, wqe->length, wqe->wr.wr.rdma.remote_addr, wqe->wr.wr.rdma.rkey, @@ -394,11 +344,8 @@ again: case IB_WR_ATOMIC_CMP_AND_SWP: case IB_WR_ATOMIC_FETCH_AND_ADD: - if (unlikely(!(qp->qp_access_flags & - IB_ACCESS_REMOTE_ATOMIC))) { - wc.status = IB_WC_REM_INV_REQ_ERR; - goto err; - } + if (unlikely(!(qp->qp_access_flags & IB_ACCESS_REMOTE_ATOMIC))) + goto inv_err; if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, sizeof(u64), wqe->wr.wr.atomic.remote_addr, wqe->wr.wr.atomic.rkey, @@ -415,7 +362,8 @@ again: goto send_comp; default: - goto done; + send_status = IB_WC_LOC_QP_OP_ERR; + goto serr; } sge = &sqp->s_sge.sge; @@ -458,14 +406,11 @@ again: wc.opcode = IB_WC_RECV; wc.wr_id = qp->r_wr_id; wc.status = IB_WC_SUCCESS; - wc.vendor_err = 0; wc.byte_len = wqe->length; wc.qp = &qp->ibqp; wc.src_qp = qp->remote_qpn; - wc.pkey_index = 0; wc.slid = qp->remote_ah_attr.dlid; wc.sl = qp->remote_ah_attr.sl; - wc.dlid_path_bits = 0; wc.port_num = 1; /* Signal completion event if the solicited bit is set. */ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, @@ -473,9 +418,63 @@ again: send_comp: sqp->s_rnr_retry = sqp->s_rnr_retry_cnt; - ipath_send_complete(sqp, wqe, IB_WC_SUCCESS); + ipath_send_complete(sqp, wqe, send_status); goto again; +rnr_nak: + /* Handle RNR NAK */ + if (qp->ibqp.qp_type == IB_QPT_UC) + goto send_comp; + /* + * Note: we don't need the s_lock held since the BUSY flag + * makes this single threaded. + */ + if (sqp->s_rnr_retry == 0) { + send_status = IB_WC_RNR_RETRY_EXC_ERR; + goto serr; + } + if (sqp->s_rnr_retry_cnt < 7) + sqp->s_rnr_retry--; + spin_lock_irqsave(&sqp->s_lock, flags); + if (!(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_RECV_OK)) + goto unlock; + dev->n_rnr_naks++; + sqp->s_rnr_timeout = ib_ipath_rnr_table[qp->r_min_rnr_timer]; + ipath_insert_rnr_queue(sqp); + goto unlock; + +inv_err: + send_status = IB_WC_REM_INV_REQ_ERR; + wc.status = IB_WC_LOC_QP_OP_ERR; + goto err; + +acc_err: + send_status = IB_WC_REM_ACCESS_ERR; + wc.status = IB_WC_LOC_PROT_ERR; +err: + /* responder goes to error state */ + ipath_rc_error(qp, wc.status); + +serr: + spin_lock_irqsave(&sqp->s_lock, flags); + ipath_send_complete(sqp, wqe, send_status); + if (sqp->ibqp.qp_type == IB_QPT_RC) { + int lastwqe = ipath_error_qp(sqp, IB_WC_WR_FLUSH_ERR); + + sqp->s_flags &= ~IPATH_S_BUSY; + spin_unlock_irqrestore(&sqp->s_lock, flags); + if (lastwqe) { + struct ib_event ev; + + ev.device = sqp->ibqp.device; + ev.element.qp = &sqp->ibqp; + ev.event = IB_EVENT_QP_LAST_WQE_REACHED; + sqp->ibqp.event_handler(&ev, sqp->ibqp.qp_context); + } + goto done; + } +unlock: + spin_unlock_irqrestore(&sqp->s_lock, flags); done: if (atomic_dec_and_test(&qp->refcount)) wake_up(&qp->wait); @@ -651,21 +650,15 @@ void ipath_send_complete(struct ipath_qp *qp, struct ipath_swqe *wqe, status != IB_WC_SUCCESS) { struct ib_wc wc; + memset(&wc, 0, sizeof wc); wc.wr_id = wqe->wr.wr_id; wc.status = status; wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; - wc.vendor_err = 0; - wc.byte_len = wqe->length; - wc.imm_data = 0; wc.qp = &qp->ibqp; - wc.src_qp = 0; - wc.wc_flags = 0; - wc.pkey_index = 0; - wc.slid = 0; - wc.sl = 0; - wc.dlid_path_bits = 0; - wc.port_num = 0; - ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 0); + if (status == IB_WC_SUCCESS) + wc.byte_len = wqe->length; + ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, + status != IB_WC_SUCCESS); } spin_lock_irqsave(&qp->s_lock, flags); diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index 5015cd2..22bb42d 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c @@ -744,12 +744,10 @@ static void ipath_ib_timer(struct ipath_ibdev *dev) /* XXX What if timer fires again while this is running? */ for (qp = resend; qp != NULL; qp = qp->timer_next) { - struct ib_wc wc; - spin_lock_irqsave(&qp->s_lock, flags); if (qp->s_last != qp->s_tail && qp->state == IB_QPS_RTS) { dev->n_timeouts++; - ipath_restart_rc(qp, qp->s_last_psn + 1, &wc); + ipath_restart_rc(qp, qp->s_last_psn + 1); } spin_unlock_irqrestore(&qp->s_lock, flags); diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h index 6514aa8..4c7c2aa8 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.h +++ b/drivers/infiniband/hw/ipath/ipath_verbs.h @@ -710,8 +710,6 @@ void ipath_free_all_qps(struct ipath_qp_table *qpt); int ipath_init_qp_table(struct ipath_ibdev *idev, int size); -void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc); - void ipath_get_credit(struct ipath_qp *qp, u32 aeth); unsigned ipath_ib_rate_to_mult(enum ib_rate rate); @@ -729,7 +727,9 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, int has_grh, void *data, u32 tlen, struct ipath_qp *qp); -void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc); +void ipath_restart_rc(struct ipath_qp *qp, u32 psn); + +void ipath_rc_error(struct ipath_qp *qp, enum ib_wc_status err); int ipath_post_ud_send(struct ipath_qp *qp, struct ib_send_wr *wr); -- cgit v1.1 From e509be898d8937634437caa474b57ac12795e5bc Mon Sep 17 00:00:00 2001 From: Ralph Campbell Date: Tue, 13 May 2008 11:41:29 -0700 Subject: IB/ipath: Fix many locking issues when switching to error state The send DMA hardware queue voided a number of prior assumptions about when a send is complete which led to completions being generated out of order. There were also a number of locking issues when switching the QP to the error or reset states, and we implement the IB_QPS_SQD state. Signed-off-by: Ralph Campbell Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_qp.c | 183 +++++++++++++------------- drivers/infiniband/hw/ipath/ipath_rc.c | 151 +++++++++++++-------- drivers/infiniband/hw/ipath/ipath_ruc.c | 168 +++++++++++++++-------- drivers/infiniband/hw/ipath/ipath_uc.c | 57 +++++--- drivers/infiniband/hw/ipath/ipath_ud.c | 66 +++++++--- drivers/infiniband/hw/ipath/ipath_user_sdma.h | 2 - drivers/infiniband/hw/ipath/ipath_verbs.c | 174 ++++++++++++++++-------- drivers/infiniband/hw/ipath/ipath_verbs.h | 57 ++++++-- 8 files changed, 554 insertions(+), 304 deletions(-) diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c index 6f98632..4715911 100644 --- a/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/drivers/infiniband/hw/ipath/ipath_qp.c @@ -242,7 +242,6 @@ static void ipath_free_qp(struct ipath_qp_table *qpt, struct ipath_qp *qp) { struct ipath_qp *q, **qpp; unsigned long flags; - int fnd = 0; spin_lock_irqsave(&qpt->lock, flags); @@ -253,51 +252,40 @@ static void ipath_free_qp(struct ipath_qp_table *qpt, struct ipath_qp *qp) *qpp = qp->next; qp->next = NULL; atomic_dec(&qp->refcount); - fnd = 1; break; } } spin_unlock_irqrestore(&qpt->lock, flags); - - if (!fnd) - return; - - free_qpn(qpt, qp->ibqp.qp_num); - - wait_event(qp->wait, !atomic_read(&qp->refcount)); } /** - * ipath_free_all_qps - remove all QPs from the table + * ipath_free_all_qps - check for QPs still in use * @qpt: the QP table to empty + * + * There should not be any QPs still in use. + * Free memory for table. */ -void ipath_free_all_qps(struct ipath_qp_table *qpt) +unsigned ipath_free_all_qps(struct ipath_qp_table *qpt) { unsigned long flags; - struct ipath_qp *qp, *nqp; - u32 n; + struct ipath_qp *qp; + u32 n, qp_inuse = 0; + spin_lock_irqsave(&qpt->lock, flags); for (n = 0; n < qpt->max; n++) { - spin_lock_irqsave(&qpt->lock, flags); qp = qpt->table[n]; qpt->table[n] = NULL; - spin_unlock_irqrestore(&qpt->lock, flags); - - while (qp) { - nqp = qp->next; - free_qpn(qpt, qp->ibqp.qp_num); - if (!atomic_dec_and_test(&qp->refcount) || - !ipath_destroy_qp(&qp->ibqp)) - ipath_dbg("QP memory leak!\n"); - qp = nqp; - } + + for (; qp; qp = qp->next) + qp_inuse++; } + spin_unlock_irqrestore(&qpt->lock, flags); - for (n = 0; n < ARRAY_SIZE(qpt->map); n++) { + for (n = 0; n < ARRAY_SIZE(qpt->map); n++) if (qpt->map[n].page) - free_page((unsigned long)qpt->map[n].page); - } + free_page((unsigned long) qpt->map[n].page); + return qp_inuse; } /** @@ -336,11 +324,12 @@ static void ipath_reset_qp(struct ipath_qp *qp, enum ib_qp_type type) qp->remote_qpn = 0; qp->qkey = 0; qp->qp_access_flags = 0; - qp->s_busy = 0; + atomic_set(&qp->s_dma_busy, 0); qp->s_flags &= IPATH_S_SIGNAL_REQ_WR; qp->s_hdrwords = 0; qp->s_wqe = NULL; qp->s_pkt_delay = 0; + qp->s_draining = 0; qp->s_psn = 0; qp->r_psn = 0; qp->r_msn = 0; @@ -353,7 +342,8 @@ static void ipath_reset_qp(struct ipath_qp *qp, enum ib_qp_type type) } qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE; qp->r_nak_state = 0; - qp->r_wrid_valid = 0; + qp->r_aflags = 0; + qp->r_flags = 0; qp->s_rnr_timeout = 0; qp->s_head = 0; qp->s_tail = 0; @@ -361,7 +351,6 @@ static void ipath_reset_qp(struct ipath_qp *qp, enum ib_qp_type type) qp->s_last = 0; qp->s_ssn = 1; qp->s_lsn = 0; - qp->s_wait_credit = 0; memset(qp->s_ack_queue, 0, sizeof(qp->s_ack_queue)); qp->r_head_ack_queue = 0; qp->s_tail_ack_queue = 0; @@ -370,7 +359,6 @@ static void ipath_reset_qp(struct ipath_qp *qp, enum ib_qp_type type) qp->r_rq.wq->head = 0; qp->r_rq.wq->tail = 0; } - qp->r_reuse_sge = 0; } /** @@ -402,39 +390,21 @@ int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err) list_del_init(&qp->piowait); spin_unlock(&dev->pending_lock); - wc.vendor_err = 0; - wc.byte_len = 0; - wc.imm_data = 0; + /* Schedule the sending tasklet to drain the send work queue. */ + if (qp->s_last != qp->s_head) + ipath_schedule_send(qp); + + memset(&wc, 0, sizeof(wc)); wc.qp = &qp->ibqp; - wc.src_qp = 0; - wc.wc_flags = 0; - wc.pkey_index = 0; - wc.slid = 0; - wc.sl = 0; - wc.dlid_path_bits = 0; - wc.port_num = 0; - if (qp->r_wrid_valid) { - qp->r_wrid_valid = 0; + wc.opcode = IB_WC_RECV; + + if (test_and_clear_bit(IPATH_R_WRID_VALID, &qp->r_aflags)) { wc.wr_id = qp->r_wr_id; - wc.opcode = IB_WC_RECV; wc.status = err; ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, 1); } wc.status = IB_WC_WR_FLUSH_ERR; - while (qp->s_last != qp->s_head) { - struct ipath_swqe *wqe = get_swqe_ptr(qp, qp->s_last); - - wc.wr_id = wqe->wr.wr_id; - wc.opcode = ib_ipath_wc_opcode[wqe->wr.opcode]; - if (++qp->s_last >= qp->s_size) - qp->s_last = 0; - ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 1); - } - qp->s_cur = qp->s_tail = qp->s_head; - qp->s_hdrwords = 0; - qp->s_ack_state = IB_OPCODE_RC_ACKNOWLEDGE; - if (qp->r_rq.wq) { struct ipath_rwq *wq; u32 head; @@ -450,7 +420,6 @@ int ipath_error_qp(struct ipath_qp *qp, enum ib_wc_status err) tail = wq->tail; if (tail >= qp->r_rq.size) tail = 0; - wc.opcode = IB_WC_RECV; while (tail != head) { wc.wr_id = get_rwqe_ptr(&qp->r_rq, tail)->wr_id; if (++tail >= qp->r_rq.size) @@ -482,11 +451,10 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, struct ipath_ibdev *dev = to_idev(ibqp->device); struct ipath_qp *qp = to_iqp(ibqp); enum ib_qp_state cur_state, new_state; - unsigned long flags; int lastwqe = 0; int ret; - spin_lock_irqsave(&qp->s_lock, flags); + spin_lock_irq(&qp->s_lock); cur_state = attr_mask & IB_QP_CUR_STATE ? attr->cur_qp_state : qp->state; @@ -539,16 +507,42 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, switch (new_state) { case IB_QPS_RESET: + if (qp->state != IB_QPS_RESET) { + qp->state = IB_QPS_RESET; + spin_lock(&dev->pending_lock); + if (!list_empty(&qp->timerwait)) + list_del_init(&qp->timerwait); + if (!list_empty(&qp->piowait)) + list_del_init(&qp->piowait); + spin_unlock(&dev->pending_lock); + qp->s_flags &= ~IPATH_S_ANY_WAIT; + spin_unlock_irq(&qp->s_lock); + /* Stop the sending tasklet */ + tasklet_kill(&qp->s_task); + wait_event(qp->wait_dma, !atomic_read(&qp->s_dma_busy)); + spin_lock_irq(&qp->s_lock); + } ipath_reset_qp(qp, ibqp->qp_type); break; + case IB_QPS_SQD: + qp->s_draining = qp->s_last != qp->s_cur; + qp->state = new_state; + break; + + case IB_QPS_SQE: + if (qp->ibqp.qp_type == IB_QPT_RC) + goto inval; + qp->state = new_state; + break; + case IB_QPS_ERR: lastwqe = ipath_error_qp(qp, IB_WC_WR_FLUSH_ERR); break; default: + qp->state = new_state; break; - } if (attr_mask & IB_QP_PKEY_INDEX) @@ -601,8 +595,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, if (attr_mask & IB_QP_MAX_QP_RD_ATOMIC) qp->s_max_rd_atomic = attr->max_rd_atomic; - qp->state = new_state; - spin_unlock_irqrestore(&qp->s_lock, flags); + spin_unlock_irq(&qp->s_lock); if (lastwqe) { struct ib_event ev; @@ -616,7 +609,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, goto bail; inval: - spin_unlock_irqrestore(&qp->s_lock, flags); + spin_unlock_irq(&qp->s_lock); ret = -EINVAL; bail: @@ -647,7 +640,7 @@ int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, attr->pkey_index = qp->s_pkey_index; attr->alt_pkey_index = 0; attr->en_sqd_async_notify = 0; - attr->sq_draining = 0; + attr->sq_draining = qp->s_draining; attr->max_rd_atomic = qp->s_max_rd_atomic; attr->max_dest_rd_atomic = qp->r_max_rd_atomic; attr->min_rnr_timer = qp->r_min_rnr_timer; @@ -837,6 +830,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, spin_lock_init(&qp->r_rq.lock); atomic_set(&qp->refcount, 0); init_waitqueue_head(&qp->wait); + init_waitqueue_head(&qp->wait_dma); tasklet_init(&qp->s_task, ipath_do_send, (unsigned long)qp); INIT_LIST_HEAD(&qp->piowait); INIT_LIST_HEAD(&qp->timerwait); @@ -930,6 +924,7 @@ bail_ip: else vfree(qp->r_rq.wq); ipath_free_qp(&dev->qp_table, qp); + free_qpn(&dev->qp_table, qp->ibqp.qp_num); bail_qp: kfree(qp); bail_swq: @@ -951,41 +946,44 @@ int ipath_destroy_qp(struct ib_qp *ibqp) { struct ipath_qp *qp = to_iqp(ibqp); struct ipath_ibdev *dev = to_idev(ibqp->device); - unsigned long flags; - spin_lock_irqsave(&qp->s_lock, flags); - qp->state = IB_QPS_ERR; - spin_unlock_irqrestore(&qp->s_lock, flags); - spin_lock(&dev->n_qps_lock); - dev->n_qps_allocated--; - spin_unlock(&dev->n_qps_lock); + /* Make sure HW and driver activity is stopped. */ + spin_lock_irq(&qp->s_lock); + if (qp->state != IB_QPS_RESET) { + qp->state = IB_QPS_RESET; + spin_lock(&dev->pending_lock); + if (!list_empty(&qp->timerwait)) + list_del_init(&qp->timerwait); + if (!list_empty(&qp->piowait)) + list_del_init(&qp->piowait); + spin_unlock(&dev->pending_lock); + qp->s_flags &= ~IPATH_S_ANY_WAIT; + spin_unlock_irq(&qp->s_lock); + /* Stop the sending tasklet */ + tasklet_kill(&qp->s_task); + wait_event(qp->wait_dma, !atomic_read(&qp->s_dma_busy)); + } else + spin_unlock_irq(&qp->s_lock); - /* Stop the sending tasklet. */ - tasklet_kill(&qp->s_task); + ipath_free_qp(&dev->qp_table, qp); if (qp->s_tx) { atomic_dec(&qp->refcount); if (qp->s_tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEBUF) kfree(qp->s_tx->txreq.map_addr); + spin_lock_irq(&dev->pending_lock); + list_add(&qp->s_tx->txreq.list, &dev->txreq_free); + spin_unlock_irq(&dev->pending_lock); + qp->s_tx = NULL; } - /* Make sure the QP isn't on the timeout list. */ - spin_lock_irqsave(&dev->pending_lock, flags); - if (!list_empty(&qp->timerwait)) - list_del_init(&qp->timerwait); - if (!list_empty(&qp->piowait)) - list_del_init(&qp->piowait); - if (qp->s_tx) - list_add(&qp->s_tx->txreq.list, &dev->txreq_free); - spin_unlock_irqrestore(&dev->pending_lock, flags); + wait_event(qp->wait, !atomic_read(&qp->refcount)); - /* - * Make sure that the QP is not in the QPN table so receive - * interrupts will discard packets for this QP. XXX Also remove QP - * from multicast table. - */ - if (atomic_read(&qp->refcount) != 0) - ipath_free_qp(&dev->qp_table, qp); + /* all user's cleaned up, mark it available */ + free_qpn(&dev->qp_table, qp->ibqp.qp_num); + spin_lock(&dev->n_qps_lock); + dev->n_qps_allocated--; + spin_unlock(&dev->n_qps_lock); if (qp->ip) kref_put(&qp->ip->ref, ipath_release_mmap_info); @@ -1055,9 +1053,10 @@ void ipath_get_credit(struct ipath_qp *qp, u32 aeth) } /* Restart sending if it was blocked due to lack of credits. */ - if (qp->s_cur != qp->s_head && + if ((qp->s_flags & IPATH_S_WAIT_SSN_CREDIT) && + qp->s_cur != qp->s_head && (qp->s_lsn == (u32) -1 || ipath_cmp24(get_swqe_ptr(qp, qp->s_cur)->ssn, qp->s_lsn + 1) <= 0)) - tasklet_hi_schedule(&qp->s_task); + ipath_schedule_send(qp); } diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index b4b26c3..5b5276a 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c @@ -92,6 +92,10 @@ static int ipath_make_rc_ack(struct ipath_ibdev *dev, struct ipath_qp *qp, u32 bth0; u32 bth2; + /* Don't send an ACK if we aren't supposed to. */ + if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) + goto bail; + /* header size in 32-bit words LRH+BTH = (8+12)/4. */ hwords = 5; @@ -238,14 +242,25 @@ int ipath_make_rc_req(struct ipath_qp *qp) ipath_make_rc_ack(dev, qp, ohdr, pmtu)) goto done; - if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK) || - qp->s_rnr_timeout || qp->s_wait_credit) - goto bail; + if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK)) { + if (!(ib_ipath_state_ops[qp->state] & IPATH_FLUSH_SEND)) + goto bail; + /* We are in the error state, flush the work request. */ + if (qp->s_last == qp->s_head) + goto bail; + /* If DMAs are in progress, we can't flush immediately. */ + if (atomic_read(&qp->s_dma_busy)) { + qp->s_flags |= IPATH_S_WAIT_DMA; + goto bail; + } + wqe = get_swqe_ptr(qp, qp->s_last); + ipath_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR); + goto done; + } - /* Limit the number of packets sent without an ACK. */ - if (ipath_cmp24(qp->s_psn, qp->s_last_psn + IPATH_PSN_CREDIT) > 0) { - qp->s_wait_credit = 1; - dev->n_rc_stalls++; + /* Leave BUSY set until RNR timeout. */ + if (qp->s_rnr_timeout) { + qp->s_flags |= IPATH_S_WAITING; goto bail; } @@ -257,6 +272,9 @@ int ipath_make_rc_req(struct ipath_qp *qp) wqe = get_swqe_ptr(qp, qp->s_cur); switch (qp->s_state) { default: + if (!(ib_ipath_state_ops[qp->state] & + IPATH_PROCESS_NEXT_SEND_OK)) + goto bail; /* * Resend an old request or start a new one. * @@ -294,8 +312,10 @@ int ipath_make_rc_req(struct ipath_qp *qp) case IB_WR_SEND_WITH_IMM: /* If no credit, return. */ if (qp->s_lsn != (u32) -1 && - ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0) + ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0) { + qp->s_flags |= IPATH_S_WAIT_SSN_CREDIT; goto bail; + } wqe->lpsn = wqe->psn; if (len > pmtu) { wqe->lpsn += (len - 1) / pmtu; @@ -325,8 +345,10 @@ int ipath_make_rc_req(struct ipath_qp *qp) case IB_WR_RDMA_WRITE_WITH_IMM: /* If no credit, return. */ if (qp->s_lsn != (u32) -1 && - ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0) + ipath_cmp24(wqe->ssn, qp->s_lsn + 1) > 0) { + qp->s_flags |= IPATH_S_WAIT_SSN_CREDIT; goto bail; + } ohdr->u.rc.reth.vaddr = cpu_to_be64(wqe->wr.wr.rdma.remote_addr); ohdr->u.rc.reth.rkey = @@ -570,7 +592,11 @@ int ipath_make_rc_req(struct ipath_qp *qp) ipath_make_ruc_header(dev, qp, ohdr, bth0 | (qp->s_state << 24), bth2); done: ret = 1; + goto unlock; + bail: + qp->s_flags &= ~IPATH_S_BUSY; +unlock: spin_unlock_irqrestore(&qp->s_lock, flags); return ret; } @@ -606,7 +632,11 @@ static void send_rc_ack(struct ipath_qp *qp) spin_unlock_irqrestore(&qp->s_lock, flags); + /* Don't try to send ACKs if the link isn't ACTIVE */ dd = dev->dd; + if (!(dd->ipath_flags & IPATH_LINKACTIVE)) + goto done; + piobuf = ipath_getpiobuf(dd, 0, NULL); if (!piobuf) { /* @@ -668,15 +698,16 @@ static void send_rc_ack(struct ipath_qp *qp) goto done; queue_ack: - dev->n_rc_qacks++; - qp->s_flags |= IPATH_S_ACK_PENDING; - qp->s_nak_state = qp->r_nak_state; - qp->s_ack_psn = qp->r_ack_psn; + if (ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK) { + dev->n_rc_qacks++; + qp->s_flags |= IPATH_S_ACK_PENDING; + qp->s_nak_state = qp->r_nak_state; + qp->s_ack_psn = qp->r_ack_psn; + + /* Schedule the send tasklet. */ + ipath_schedule_send(qp); + } spin_unlock_irqrestore(&qp->s_lock, flags); - - /* Call ipath_do_rc_send() in another thread. */ - tasklet_hi_schedule(&qp->s_task); - done: return; } @@ -735,7 +766,7 @@ static void reset_psn(struct ipath_qp *qp, u32 psn) /* * Set the state to restart in the middle of a request. * Don't change the s_sge, s_cur_sge, or s_cur_size. - * See ipath_do_rc_send(). + * See ipath_make_rc_req(). */ switch (opcode) { case IB_WR_SEND: @@ -801,7 +832,7 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn) dev->n_rc_resends += (qp->s_psn - psn) & IPATH_PSN_MASK; reset_psn(qp, psn); - tasklet_hi_schedule(&qp->s_task); + ipath_schedule_send(qp); bail: return; @@ -809,13 +840,7 @@ bail: static inline void update_last_psn(struct ipath_qp *qp, u32 psn) { - if (qp->s_last_psn != psn) { - qp->s_last_psn = psn; - if (qp->s_wait_credit) { - qp->s_wait_credit = 0; - tasklet_hi_schedule(&qp->s_task); - } - } + qp->s_last_psn = psn; } /** @@ -915,14 +940,10 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, wqe->wr.opcode == IB_WR_ATOMIC_FETCH_AND_ADD)) { qp->s_num_rd_atomic--; /* Restart sending task if fence is complete */ - if ((qp->s_flags & IPATH_S_FENCE_PENDING) && - !qp->s_num_rd_atomic) { - qp->s_flags &= ~IPATH_S_FENCE_PENDING; - tasklet_hi_schedule(&qp->s_task); - } else if (qp->s_flags & IPATH_S_RDMAR_PENDING) { - qp->s_flags &= ~IPATH_S_RDMAR_PENDING; - tasklet_hi_schedule(&qp->s_task); - } + if (((qp->s_flags & IPATH_S_FENCE_PENDING) && + !qp->s_num_rd_atomic) || + qp->s_flags & IPATH_S_RDMAR_PENDING) + ipath_schedule_send(qp); } /* Post a send completion queue entry if requested. */ if (!(qp->s_flags & IPATH_S_SIGNAL_REQ_WR) || @@ -956,6 +977,8 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, } else { if (++qp->s_last >= qp->s_size) qp->s_last = 0; + if (qp->state == IB_QPS_SQD && qp->s_last == qp->s_cur) + qp->s_draining = 0; if (qp->s_last == qp->s_tail) break; wqe = get_swqe_ptr(qp, qp->s_last); @@ -979,7 +1002,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, */ if (ipath_cmp24(qp->s_psn, psn) <= 0) { reset_psn(qp, psn + 1); - tasklet_hi_schedule(&qp->s_task); + ipath_schedule_send(qp); } } else if (ipath_cmp24(qp->s_psn, psn) <= 0) { qp->s_state = OP(SEND_LAST); @@ -1018,6 +1041,7 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode, ib_ipath_rnr_table[(aeth >> IPATH_AETH_CREDIT_SHIFT) & IPATH_AETH_CREDIT_MASK]; ipath_insert_rnr_queue(qp); + ipath_schedule_send(qp); goto bail; case 3: /* NAK */ @@ -1108,6 +1132,10 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, spin_lock_irqsave(&qp->s_lock, flags); + /* Double check we can process this now that we hold the s_lock. */ + if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) + goto ack_done; + /* Ignore invalid responses. */ if (ipath_cmp24(psn, qp->s_next_psn) >= 0) goto ack_done; @@ -1343,7 +1371,12 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev, psn &= IPATH_PSN_MASK; e = NULL; old_req = 1; + spin_lock_irqsave(&qp->s_lock, flags); + /* Double check we can process this now that we hold the s_lock. */ + if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) + goto unlock_done; + for (i = qp->r_head_ack_queue; ; i = prev) { if (i == qp->s_tail_ack_queue) old_req = 0; @@ -1471,7 +1504,7 @@ static inline int ipath_rc_rcv_error(struct ipath_ibdev *dev, break; } qp->r_nak_state = 0; - tasklet_hi_schedule(&qp->s_task); + ipath_schedule_send(qp); unlock_done: spin_unlock_irqrestore(&qp->s_lock, flags); @@ -1503,18 +1536,15 @@ void ipath_rc_error(struct ipath_qp *qp, enum ib_wc_status err) static inline void ipath_update_ack_queue(struct ipath_qp *qp, unsigned n) { - unsigned long flags; unsigned next; next = n + 1; if (next > IPATH_MAX_RDMA_ATOMIC) next = 0; - spin_lock_irqsave(&qp->s_lock, flags); if (n == qp->s_tail_ack_queue) { qp->s_tail_ack_queue = next; qp->s_ack_state = OP(ACKNOWLEDGE); } - spin_unlock_irqrestore(&qp->s_lock, flags); } /** @@ -1543,6 +1573,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, int diff; struct ib_reth *reth; int header_in_data; + unsigned long flags; /* Validate the SLID. See Ch. 9.6.1.5 */ if (unlikely(be16_to_cpu(hdr->lrh[3]) != qp->remote_ah_attr.dlid)) @@ -1690,9 +1721,8 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, goto nack_inv; ipath_copy_sge(&qp->r_sge, data, tlen); qp->r_msn++; - if (!qp->r_wrid_valid) + if (!test_and_clear_bit(IPATH_R_WRID_VALID, &qp->r_aflags)) break; - qp->r_wrid_valid = 0; wc.wr_id = qp->r_wr_id; wc.status = IB_WC_SUCCESS; if (opcode == OP(RDMA_WRITE_LAST_WITH_IMMEDIATE) || @@ -1764,9 +1794,13 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, next = qp->r_head_ack_queue + 1; if (next > IPATH_MAX_RDMA_ATOMIC) next = 0; + spin_lock_irqsave(&qp->s_lock, flags); + /* Double check we can process this while holding the s_lock. */ + if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) + goto unlock; if (unlikely(next == qp->s_tail_ack_queue)) { if (!qp->s_ack_queue[next].sent) - goto nack_inv; + goto nack_inv_unlck; ipath_update_ack_queue(qp, next); } e = &qp->s_ack_queue[qp->r_head_ack_queue]; @@ -1787,7 +1821,7 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, ok = ipath_rkey_ok(qp, &e->rdma_sge, len, vaddr, rkey, IB_ACCESS_REMOTE_READ); if (unlikely(!ok)) - goto nack_acc; + goto nack_acc_unlck; /* * Update the next expected PSN. We add 1 later * below, so only add the remainder here. @@ -1814,13 +1848,12 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, qp->r_psn++; qp->r_state = opcode; qp->r_nak_state = 0; - barrier(); qp->r_head_ack_queue = next; - /* Call ipath_do_rc_send() in another thread. */ - tasklet_hi_schedule(&qp->s_task); + /* Schedule the send tasklet. */ + ipath_schedule_send(qp); - goto done; + goto unlock; } case OP(COMPARE_SWAP): @@ -1839,9 +1872,13 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, next = qp->r_head_ack_queue + 1; if (next > IPATH_MAX_RDMA_ATOMIC) next = 0; + spin_lock_irqsave(&qp->s_lock, flags); + /* Double check we can process this while holding the s_lock. */ + if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) + goto unlock; if (unlikely(next == qp->s_tail_ack_queue)) { if (!qp->s_ack_queue[next].sent) - goto nack_inv; + goto nack_inv_unlck; ipath_update_ack_queue(qp, next); } if (!header_in_data) @@ -1851,13 +1888,13 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, vaddr = ((u64) be32_to_cpu(ateth->vaddr[0]) << 32) | be32_to_cpu(ateth->vaddr[1]); if (unlikely(vaddr & (sizeof(u64) - 1))) - goto nack_inv; + goto nack_inv_unlck; rkey = be32_to_cpu(ateth->rkey); /* Check rkey & NAK */ if (unlikely(!ipath_rkey_ok(qp, &qp->r_sge, sizeof(u64), vaddr, rkey, IB_ACCESS_REMOTE_ATOMIC))) - goto nack_acc; + goto nack_acc_unlck; /* Perform atomic OP and save result. */ maddr = (atomic64_t *) qp->r_sge.sge.vaddr; sdata = be64_to_cpu(ateth->swap_data); @@ -1874,13 +1911,12 @@ void ipath_rc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, qp->r_psn++; qp->r_state = opcode; qp->r_nak_state = 0; - barrier(); qp->r_head_ack_queue = next; - /* Call ipath_do_rc_send() in another thread. */ - tasklet_hi_schedule(&qp->s_task); + /* Schedule the send tasklet. */ + ipath_schedule_send(qp); - goto done; + goto unlock; } default: @@ -1901,19 +1937,26 @@ rnr_nak: qp->r_ack_psn = qp->r_psn; goto send_ack; +nack_inv_unlck: + spin_unlock_irqrestore(&qp->s_lock, flags); nack_inv: ipath_rc_error(qp, IB_WC_LOC_QP_OP_ERR); qp->r_nak_state = IB_NAK_INVALID_REQUEST; qp->r_ack_psn = qp->r_psn; goto send_ack; +nack_acc_unlck: + spin_unlock_irqrestore(&qp->s_lock, flags); nack_acc: ipath_rc_error(qp, IB_WC_LOC_PROT_ERR); qp->r_nak_state = IB_NAK_REMOTE_ACCESS_ERROR; qp->r_ack_psn = qp->r_psn; send_ack: send_rc_ack(qp); + goto done; +unlock: + spin_unlock_irqrestore(&qp->s_lock, flags); done: return; } diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c index c716a03..a4b5521 100644 --- a/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/drivers/infiniband/hw/ipath/ipath_ruc.c @@ -78,6 +78,7 @@ const u32 ib_ipath_rnr_table[32] = { * ipath_insert_rnr_queue - put QP on the RNR timeout list for the device * @qp: the QP * + * Called with the QP s_lock held and interrupts disabled. * XXX Use a simple list for now. We might need a priority * queue if we have lots of QPs waiting for RNR timeouts * but that should be rare. @@ -85,9 +86,9 @@ const u32 ib_ipath_rnr_table[32] = { void ipath_insert_rnr_queue(struct ipath_qp *qp) { struct ipath_ibdev *dev = to_idev(qp->ibqp.device); - unsigned long flags; - spin_lock_irqsave(&dev->pending_lock, flags); + /* We already did a spin_lock_irqsave(), so just use spin_lock */ + spin_lock(&dev->pending_lock); if (list_empty(&dev->rnrwait)) list_add(&qp->timerwait, &dev->rnrwait); else { @@ -109,7 +110,7 @@ void ipath_insert_rnr_queue(struct ipath_qp *qp) nqp->s_rnr_timeout -= qp->s_rnr_timeout; list_add(&qp->timerwait, l); } - spin_unlock_irqrestore(&dev->pending_lock, flags); + spin_unlock(&dev->pending_lock); } /** @@ -185,6 +186,11 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) } spin_lock_irqsave(&rq->lock, flags); + if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) { + ret = 0; + goto unlock; + } + wq = rq->wq; tail = wq->tail; /* Validate tail before using it since it is user writable. */ @@ -192,9 +198,8 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) tail = 0; do { if (unlikely(tail == wq->head)) { - spin_unlock_irqrestore(&rq->lock, flags); ret = 0; - goto bail; + goto unlock; } /* Make sure entry is read after head index is read. */ smp_rmb(); @@ -207,7 +212,7 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) wq->tail = tail; ret = 1; - qp->r_wrid_valid = 1; + set_bit(IPATH_R_WRID_VALID, &qp->r_aflags); if (handler) { u32 n; @@ -234,8 +239,8 @@ int ipath_get_rwqe(struct ipath_qp *qp, int wr_id_only) goto bail; } } +unlock: spin_unlock_irqrestore(&rq->lock, flags); - bail: return ret; } @@ -263,35 +268,59 @@ static void ipath_ruc_loopback(struct ipath_qp *sqp) atomic64_t *maddr; enum ib_wc_status send_status; + /* + * Note that we check the responder QP state after + * checking the requester's state. + */ qp = ipath_lookup_qpn(&dev->qp_table, sqp->remote_qpn); - if (!qp) { - dev->n_pkt_drops++; - return; - } -again: spin_lock_irqsave(&sqp->s_lock, flags); - if (!(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_SEND_OK) || - sqp->s_rnr_timeout) { - spin_unlock_irqrestore(&sqp->s_lock, flags); - goto done; - } + /* Return if we are already busy processing a work request. */ + if ((sqp->s_flags & (IPATH_S_BUSY | IPATH_S_ANY_WAIT)) || + !(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_OR_FLUSH_SEND)) + goto unlock; - /* Get the next send request. */ - if (sqp->s_last == sqp->s_head) { - /* Send work queue is empty. */ - spin_unlock_irqrestore(&sqp->s_lock, flags); - goto done; + sqp->s_flags |= IPATH_S_BUSY; + +again: + if (sqp->s_last == sqp->s_head) + goto clr_busy; + wqe = get_swqe_ptr(sqp, sqp->s_last); + + /* Return if it is not OK to start a new work reqeust. */ + if (!(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_NEXT_SEND_OK)) { + if (!(ib_ipath_state_ops[sqp->state] & IPATH_FLUSH_SEND)) + goto clr_busy; + /* We are in the error state, flush the work request. */ + send_status = IB_WC_WR_FLUSH_ERR; + goto flush_send; } /* * We can rely on the entry not changing without the s_lock * being held until we update s_last. + * We increment s_cur to indicate s_last is in progress. */ - wqe = get_swqe_ptr(sqp, sqp->s_last); + if (sqp->s_last == sqp->s_cur) { + if (++sqp->s_cur >= sqp->s_size) + sqp->s_cur = 0; + } spin_unlock_irqrestore(&sqp->s_lock, flags); + if (!qp || !(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) { + dev->n_pkt_drops++; + /* + * For RC, the requester would timeout and retry so + * shortcut the timeouts and just signal too many retries. + */ + if (sqp->ibqp.qp_type == IB_QPT_RC) + send_status = IB_WC_RETRY_EXC_ERR; + else + send_status = IB_WC_SUCCESS; + goto serr; + } + memset(&wc, 0, sizeof wc); send_status = IB_WC_SUCCESS; @@ -396,8 +425,7 @@ again: sqp->s_len -= len; } - if (wqe->wr.opcode == IB_WR_RDMA_WRITE || - wqe->wr.opcode == IB_WR_RDMA_READ) + if (!test_and_clear_bit(IPATH_R_WRID_VALID, &qp->r_aflags)) goto send_comp; if (wqe->wr.opcode == IB_WR_RDMA_WRITE_WITH_IMM) @@ -417,6 +445,8 @@ again: wqe->wr.send_flags & IB_SEND_SOLICITED); send_comp: + spin_lock_irqsave(&sqp->s_lock, flags); +flush_send: sqp->s_rnr_retry = sqp->s_rnr_retry_cnt; ipath_send_complete(sqp, wqe, send_status); goto again; @@ -437,11 +467,12 @@ rnr_nak: sqp->s_rnr_retry--; spin_lock_irqsave(&sqp->s_lock, flags); if (!(ib_ipath_state_ops[sqp->state] & IPATH_PROCESS_RECV_OK)) - goto unlock; + goto clr_busy; + sqp->s_flags |= IPATH_S_WAITING; dev->n_rnr_naks++; sqp->s_rnr_timeout = ib_ipath_rnr_table[qp->r_min_rnr_timer]; ipath_insert_rnr_queue(sqp); - goto unlock; + goto clr_busy; inv_err: send_status = IB_WC_REM_INV_REQ_ERR; @@ -473,17 +504,19 @@ serr: } goto done; } +clr_busy: + sqp->s_flags &= ~IPATH_S_BUSY; unlock: spin_unlock_irqrestore(&sqp->s_lock, flags); done: - if (atomic_dec_and_test(&qp->refcount)) + if (qp && atomic_dec_and_test(&qp->refcount)) wake_up(&qp->wait); } static void want_buffer(struct ipath_devdata *dd, struct ipath_qp *qp) { if (!(dd->ipath_flags & IPATH_HAS_SEND_DMA) || - qp->ibqp.qp_type == IB_QPT_SMI) { + qp->ibqp.qp_type == IB_QPT_SMI) { unsigned long flags; spin_lock_irqsave(&dd->ipath_sendctrl_lock, flags); @@ -501,26 +534,36 @@ static void want_buffer(struct ipath_devdata *dd, struct ipath_qp *qp) * @dev: the device we ran out of buffers on * * Called when we run out of PIO buffers. + * If we are now in the error state, return zero to flush the + * send work request. */ -static void ipath_no_bufs_available(struct ipath_qp *qp, +static int ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev) { unsigned long flags; + int ret = 1; /* * Note that as soon as want_buffer() is called and * possibly before it returns, ipath_ib_piobufavail() - * could be called. If we are still in the tasklet function, - * tasklet_hi_schedule() will not call us until the next time - * tasklet_hi_schedule() is called. - * We leave the busy flag set so that another post send doesn't - * try to put the same QP on the piowait list again. + * could be called. Therefore, put QP on the piowait list before + * enabling the PIO avail interrupt. */ - spin_lock_irqsave(&dev->pending_lock, flags); - list_add_tail(&qp->piowait, &dev->piowait); - spin_unlock_irqrestore(&dev->pending_lock, flags); - want_buffer(dev->dd, qp); - dev->n_piowait++; + spin_lock_irqsave(&qp->s_lock, flags); + if (ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK) { + dev->n_piowait++; + qp->s_flags |= IPATH_S_WAITING; + qp->s_flags &= ~IPATH_S_BUSY; + spin_lock(&dev->pending_lock); + if (list_empty(&qp->piowait)) + list_add_tail(&qp->piowait, &dev->piowait); + spin_unlock(&dev->pending_lock); + } else + ret = 0; + spin_unlock_irqrestore(&qp->s_lock, flags); + if (ret) + want_buffer(dev->dd, qp); + return ret; } /** @@ -596,15 +639,13 @@ void ipath_do_send(unsigned long data) struct ipath_qp *qp = (struct ipath_qp *)data; struct ipath_ibdev *dev = to_idev(qp->ibqp.device); int (*make_req)(struct ipath_qp *qp); - - if (test_and_set_bit(IPATH_S_BUSY, &qp->s_busy)) - goto bail; + unsigned long flags; if ((qp->ibqp.qp_type == IB_QPT_RC || qp->ibqp.qp_type == IB_QPT_UC) && qp->remote_ah_attr.dlid == dev->dd->ipath_lid) { ipath_ruc_loopback(qp); - goto clear; + goto bail; } if (qp->ibqp.qp_type == IB_QPT_RC) @@ -614,6 +655,19 @@ void ipath_do_send(unsigned long data) else make_req = ipath_make_ud_req; + spin_lock_irqsave(&qp->s_lock, flags); + + /* Return if we are already busy processing a work request. */ + if ((qp->s_flags & (IPATH_S_BUSY | IPATH_S_ANY_WAIT)) || + !(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_OR_FLUSH_SEND)) { + spin_unlock_irqrestore(&qp->s_lock, flags); + goto bail; + } + + qp->s_flags |= IPATH_S_BUSY; + + spin_unlock_irqrestore(&qp->s_lock, flags); + again: /* Check for a constructed packet to be sent. */ if (qp->s_hdrwords != 0) { @@ -623,8 +677,8 @@ again: */ if (ipath_verbs_send(qp, &qp->s_hdr, qp->s_hdrwords, qp->s_cur_sge, qp->s_cur_size)) { - ipath_no_bufs_available(qp, dev); - goto bail; + if (ipath_no_bufs_available(qp, dev)) + goto bail; } dev->n_unicast_xmit++; /* Record that we sent the packet and s_hdr is empty. */ @@ -633,16 +687,20 @@ again: if (make_req(qp)) goto again; -clear: - clear_bit(IPATH_S_BUSY, &qp->s_busy); + bail:; } +/* + * This should be called with s_lock held. + */ void ipath_send_complete(struct ipath_qp *qp, struct ipath_swqe *wqe, enum ib_wc_status status) { - unsigned long flags; - u32 last; + u32 old_last, last; + + if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_OR_FLUSH_SEND)) + return; /* See ch. 11.2.4.1 and 10.7.3.1 */ if (!(qp->s_flags & IPATH_S_SIGNAL_REQ_WR) || @@ -661,10 +719,14 @@ void ipath_send_complete(struct ipath_qp *qp, struct ipath_swqe *wqe, status != IB_WC_SUCCESS); } - spin_lock_irqsave(&qp->s_lock, flags); - last = qp->s_last; + old_last = last = qp->s_last; if (++last >= qp->s_size) last = 0; qp->s_last = last; - spin_unlock_irqrestore(&qp->s_lock, flags); + if (qp->s_cur == old_last) + qp->s_cur = last; + if (qp->s_tail == old_last) + qp->s_tail = last; + if (qp->state == IB_QPS_SQD && last == qp->s_cur) + qp->s_draining = 0; } diff --git a/drivers/infiniband/hw/ipath/ipath_uc.c b/drivers/infiniband/hw/ipath/ipath_uc.c index bfe8926..7fd18e8 100644 --- a/drivers/infiniband/hw/ipath/ipath_uc.c +++ b/drivers/infiniband/hw/ipath/ipath_uc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2007 QLogic Corporation. All rights reserved. + * Copyright (c) 2006, 2007, 2008 QLogic Corporation. All rights reserved. * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. * * This software is available to you under a choice of one of two @@ -47,14 +47,30 @@ int ipath_make_uc_req(struct ipath_qp *qp) { struct ipath_other_headers *ohdr; struct ipath_swqe *wqe; + unsigned long flags; u32 hwords; u32 bth0; u32 len; u32 pmtu = ib_mtu_enum_to_int(qp->path_mtu); int ret = 0; - if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK)) + spin_lock_irqsave(&qp->s_lock, flags); + + if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK)) { + if (!(ib_ipath_state_ops[qp->state] & IPATH_FLUSH_SEND)) + goto bail; + /* We are in the error state, flush the work request. */ + if (qp->s_last == qp->s_head) + goto bail; + /* If DMAs are in progress, we can't flush immediately. */ + if (atomic_read(&qp->s_dma_busy)) { + qp->s_flags |= IPATH_S_WAIT_DMA; + goto bail; + } + wqe = get_swqe_ptr(qp, qp->s_last); + ipath_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR); goto done; + } ohdr = &qp->s_hdr.u.oth; if (qp->remote_ah_attr.ah_flags & IB_AH_GRH) @@ -69,9 +85,12 @@ int ipath_make_uc_req(struct ipath_qp *qp) qp->s_wqe = NULL; switch (qp->s_state) { default: + if (!(ib_ipath_state_ops[qp->state] & + IPATH_PROCESS_NEXT_SEND_OK)) + goto bail; /* Check if send work queue is empty. */ if (qp->s_cur == qp->s_head) - goto done; + goto bail; /* * Start a new request. */ @@ -134,7 +153,7 @@ int ipath_make_uc_req(struct ipath_qp *qp) break; default: - goto done; + goto bail; } break; @@ -194,9 +213,14 @@ int ipath_make_uc_req(struct ipath_qp *qp) ipath_make_ruc_header(to_idev(qp->ibqp.device), qp, ohdr, bth0 | (qp->s_state << 24), qp->s_next_psn++ & IPATH_PSN_MASK); +done: ret = 1; + goto unlock; -done: +bail: + qp->s_flags &= ~IPATH_S_BUSY; +unlock: + spin_unlock_irqrestore(&qp->s_lock, flags); return ret; } @@ -258,8 +282,7 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, */ opcode = be32_to_cpu(ohdr->bth[0]) >> 24; - wc.imm_data = 0; - wc.wc_flags = 0; + memset(&wc, 0, sizeof wc); /* Compare the PSN verses the expected PSN. */ if (unlikely(ipath_cmp24(psn, qp->r_psn) != 0)) { @@ -322,8 +345,8 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, case OP(SEND_ONLY): case OP(SEND_ONLY_WITH_IMMEDIATE): send_first: - if (qp->r_reuse_sge) { - qp->r_reuse_sge = 0; + if (qp->r_flags & IPATH_R_REUSE_SGE) { + qp->r_flags &= ~IPATH_R_REUSE_SGE; qp->r_sge = qp->s_rdma_read_sge; } else if (!ipath_get_rwqe(qp, 0)) { dev->n_pkt_drops++; @@ -340,13 +363,13 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, case OP(SEND_MIDDLE): /* Check for invalid length PMTU or posted rwqe len. */ if (unlikely(tlen != (hdrsize + pmtu + 4))) { - qp->r_reuse_sge = 1; + qp->r_flags |= IPATH_R_REUSE_SGE; dev->n_pkt_drops++; goto done; } qp->r_rcv_len += pmtu; if (unlikely(qp->r_rcv_len > qp->r_len)) { - qp->r_reuse_sge = 1; + qp->r_flags |= IPATH_R_REUSE_SGE; dev->n_pkt_drops++; goto done; } @@ -372,7 +395,7 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, /* Check for invalid length. */ /* XXX LAST len should be >= 1 */ if (unlikely(tlen < (hdrsize + pad + 4))) { - qp->r_reuse_sge = 1; + qp->r_flags |= IPATH_R_REUSE_SGE; dev->n_pkt_drops++; goto done; } @@ -380,7 +403,7 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, tlen -= (hdrsize + pad + 4); wc.byte_len = tlen + qp->r_rcv_len; if (unlikely(wc.byte_len > qp->r_len)) { - qp->r_reuse_sge = 1; + qp->r_flags |= IPATH_R_REUSE_SGE; dev->n_pkt_drops++; goto done; } @@ -390,14 +413,10 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, wc.wr_id = qp->r_wr_id; wc.status = IB_WC_SUCCESS; wc.opcode = IB_WC_RECV; - wc.vendor_err = 0; wc.qp = &qp->ibqp; wc.src_qp = qp->remote_qpn; - wc.pkey_index = 0; wc.slid = qp->remote_ah_attr.dlid; wc.sl = qp->remote_ah_attr.sl; - wc.dlid_path_bits = 0; - wc.port_num = 0; /* Signal completion event if the solicited bit is set. */ ipath_cq_enter(to_icq(qp->ibqp.recv_cq), &wc, (ohdr->bth[0] & @@ -488,8 +507,8 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, dev->n_pkt_drops++; goto done; } - if (qp->r_reuse_sge) - qp->r_reuse_sge = 0; + if (qp->r_flags & IPATH_R_REUSE_SGE) + qp->r_flags &= ~IPATH_R_REUSE_SGE; else if (!ipath_get_rwqe(qp, 1)) { dev->n_pkt_drops++; goto done; diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c index 8b6a261..77ca8ca 100644 --- a/drivers/infiniband/hw/ipath/ipath_ud.c +++ b/drivers/infiniband/hw/ipath/ipath_ud.c @@ -65,9 +65,9 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe) u32 length; qp = ipath_lookup_qpn(&dev->qp_table, swqe->wr.wr.ud.remote_qpn); - if (!qp) { + if (!qp || !(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_RECV_OK)) { dev->n_pkt_drops++; - goto send_comp; + goto done; } rsge.sg_list = NULL; @@ -91,14 +91,12 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe) * present on the wire. */ length = swqe->length; + memset(&wc, 0, sizeof wc); wc.byte_len = length + sizeof(struct ib_grh); if (swqe->wr.opcode == IB_WR_SEND_WITH_IMM) { wc.wc_flags = IB_WC_WITH_IMM; wc.imm_data = swqe->wr.ex.imm_data; - } else { - wc.wc_flags = 0; - wc.imm_data = 0; } /* @@ -229,7 +227,6 @@ static void ipath_ud_loopback(struct ipath_qp *sqp, struct ipath_swqe *swqe) } wc.status = IB_WC_SUCCESS; wc.opcode = IB_WC_RECV; - wc.vendor_err = 0; wc.qp = &qp->ibqp; wc.src_qp = sqp->ibqp.qp_num; /* XXX do we know which pkey matched? Only needed for GSI. */ @@ -248,8 +245,7 @@ drop: kfree(rsge.sg_list); if (atomic_dec_and_test(&qp->refcount)) wake_up(&qp->wait); -send_comp: - ipath_send_complete(sqp, swqe, IB_WC_SUCCESS); +done:; } /** @@ -264,6 +260,7 @@ int ipath_make_ud_req(struct ipath_qp *qp) struct ipath_other_headers *ohdr; struct ib_ah_attr *ah_attr; struct ipath_swqe *wqe; + unsigned long flags; u32 nwords; u32 extra_bytes; u32 bth0; @@ -271,13 +268,30 @@ int ipath_make_ud_req(struct ipath_qp *qp) u16 lid; int ret = 0; - if (unlikely(!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK))) - goto bail; + spin_lock_irqsave(&qp->s_lock, flags); + + if (!(ib_ipath_state_ops[qp->state] & IPATH_PROCESS_NEXT_SEND_OK)) { + if (!(ib_ipath_state_ops[qp->state] & IPATH_FLUSH_SEND)) + goto bail; + /* We are in the error state, flush the work request. */ + if (qp->s_last == qp->s_head) + goto bail; + /* If DMAs are in progress, we can't flush immediately. */ + if (atomic_read(&qp->s_dma_busy)) { + qp->s_flags |= IPATH_S_WAIT_DMA; + goto bail; + } + wqe = get_swqe_ptr(qp, qp->s_last); + ipath_send_complete(qp, wqe, IB_WC_WR_FLUSH_ERR); + goto done; + } if (qp->s_cur == qp->s_head) goto bail; wqe = get_swqe_ptr(qp, qp->s_cur); + if (++qp->s_cur >= qp->s_size) + qp->s_cur = 0; /* Construct the header. */ ah_attr = &to_iah(wqe->wr.wr.ud.ah)->attr; @@ -288,10 +302,23 @@ int ipath_make_ud_req(struct ipath_qp *qp) dev->n_unicast_xmit++; } else { dev->n_unicast_xmit++; - lid = ah_attr->dlid & - ~((1 << dev->dd->ipath_lmc) - 1); + lid = ah_attr->dlid & ~((1 << dev->dd->ipath_lmc) - 1); if (unlikely(lid == dev->dd->ipath_lid)) { + /* + * If DMAs are in progress, we can't generate + * a completion for the loopback packet since + * it would be out of order. + * XXX Instead of waiting, we could queue a + * zero length descriptor so we get a callback. + */ + if (atomic_read(&qp->s_dma_busy)) { + qp->s_flags |= IPATH_S_WAIT_DMA; + goto bail; + } + spin_unlock_irqrestore(&qp->s_lock, flags); ipath_ud_loopback(qp, wqe); + spin_lock_irqsave(&qp->s_lock, flags); + ipath_send_complete(qp, wqe, IB_WC_SUCCESS); goto done; } } @@ -368,11 +395,13 @@ int ipath_make_ud_req(struct ipath_qp *qp) ohdr->u.ud.deth[1] = cpu_to_be32(qp->ibqp.qp_num); done: - if (++qp->s_cur >= qp->s_size) - qp->s_cur = 0; ret = 1; + goto unlock; bail: + qp->s_flags &= ~IPATH_S_BUSY; +unlock: + spin_unlock_irqrestore(&qp->s_lock, flags); return ret; } @@ -506,8 +535,8 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, /* * Get the next work request entry to find where to put the data. */ - if (qp->r_reuse_sge) - qp->r_reuse_sge = 0; + if (qp->r_flags & IPATH_R_REUSE_SGE) + qp->r_flags &= ~IPATH_R_REUSE_SGE; else if (!ipath_get_rwqe(qp, 0)) { /* * Count VL15 packets dropped due to no receive buffer. @@ -523,7 +552,7 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, } /* Silently drop packets which are too big. */ if (wc.byte_len > qp->r_len) { - qp->r_reuse_sge = 1; + qp->r_flags |= IPATH_R_REUSE_SGE; dev->n_pkt_drops++; goto bail; } @@ -535,7 +564,8 @@ void ipath_ud_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr, ipath_skip_sge(&qp->r_sge, sizeof(struct ib_grh)); ipath_copy_sge(&qp->r_sge, data, wc.byte_len - sizeof(struct ib_grh)); - qp->r_wrid_valid = 0; + if (!test_and_clear_bit(IPATH_R_WRID_VALID, &qp->r_aflags)) + goto bail; wc.wr_id = qp->r_wr_id; wc.status = IB_WC_SUCCESS; wc.opcode = IB_WC_RECV; diff --git a/drivers/infiniband/hw/ipath/ipath_user_sdma.h b/drivers/infiniband/hw/ipath/ipath_user_sdma.h index e70946c..fc76316 100644 --- a/drivers/infiniband/hw/ipath/ipath_user_sdma.h +++ b/drivers/infiniband/hw/ipath/ipath_user_sdma.h @@ -45,8 +45,6 @@ int ipath_user_sdma_writev(struct ipath_devdata *dd, int ipath_user_sdma_make_progress(struct ipath_devdata *dd, struct ipath_user_sdma_queue *pq); -int ipath_user_sdma_pkt_sent(const struct ipath_user_sdma_queue *pq, - u32 counter); void ipath_user_sdma_queue_drain(struct ipath_devdata *dd, struct ipath_user_sdma_queue *pq); diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index 22bb42d..e0ec540 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c @@ -111,16 +111,24 @@ static unsigned int ib_ipath_disable_sma; module_param_named(disable_sma, ib_ipath_disable_sma, uint, S_IWUSR | S_IRUGO); MODULE_PARM_DESC(disable_sma, "Disable the SMA"); +/* + * Note that it is OK to post send work requests in the SQE and ERR + * states; ipath_do_send() will process them and generate error + * completions as per IB 1.2 C10-96. + */ const int ib_ipath_state_ops[IB_QPS_ERR + 1] = { [IB_QPS_RESET] = 0, [IB_QPS_INIT] = IPATH_POST_RECV_OK, [IB_QPS_RTR] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK, [IB_QPS_RTS] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK | - IPATH_POST_SEND_OK | IPATH_PROCESS_SEND_OK, + IPATH_POST_SEND_OK | IPATH_PROCESS_SEND_OK | + IPATH_PROCESS_NEXT_SEND_OK, [IB_QPS_SQD] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK | - IPATH_POST_SEND_OK, - [IB_QPS_SQE] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK, - [IB_QPS_ERR] = 0, + IPATH_POST_SEND_OK | IPATH_PROCESS_SEND_OK, + [IB_QPS_SQE] = IPATH_POST_RECV_OK | IPATH_PROCESS_RECV_OK | + IPATH_POST_SEND_OK | IPATH_FLUSH_SEND, + [IB_QPS_ERR] = IPATH_POST_RECV_OK | IPATH_FLUSH_RECV | + IPATH_POST_SEND_OK | IPATH_FLUSH_SEND, }; struct ipath_ucontext { @@ -230,18 +238,6 @@ void ipath_skip_sge(struct ipath_sge_state *ss, u32 length) } } -static void ipath_flush_wqe(struct ipath_qp *qp, struct ib_send_wr *wr) -{ - struct ib_wc wc; - - memset(&wc, 0, sizeof(wc)); - wc.wr_id = wr->wr_id; - wc.status = IB_WC_WR_FLUSH_ERR; - wc.opcode = ib_ipath_wc_opcode[wr->opcode]; - wc.qp = &qp->ibqp; - ipath_cq_enter(to_icq(qp->ibqp.send_cq), &wc, 1); -} - /* * Count the number of DMA descriptors needed to send length bytes of data. * Don't modify the ipath_sge_state to get the count. @@ -347,14 +343,8 @@ static int ipath_post_one_send(struct ipath_qp *qp, struct ib_send_wr *wr) spin_lock_irqsave(&qp->s_lock, flags); /* Check that state is OK to post send. */ - if (unlikely(!(ib_ipath_state_ops[qp->state] & IPATH_POST_SEND_OK))) { - if (qp->state != IB_QPS_SQE && qp->state != IB_QPS_ERR) - goto bail_inval; - /* C10-96 says generate a flushed completion entry. */ - ipath_flush_wqe(qp, wr); - ret = 0; - goto bail; - } + if (unlikely(!(ib_ipath_state_ops[qp->state] & IPATH_POST_SEND_OK))) + goto bail_inval; /* IB spec says that num_sge == 0 is OK. */ if (wr->num_sge > qp->s_max_sge) @@ -677,6 +667,7 @@ bail:; static void ipath_ib_timer(struct ipath_ibdev *dev) { struct ipath_qp *resend = NULL; + struct ipath_qp *rnr = NULL; struct list_head *last; struct ipath_qp *qp; unsigned long flags; @@ -703,7 +694,9 @@ static void ipath_ib_timer(struct ipath_ibdev *dev) if (--qp->s_rnr_timeout == 0) { do { list_del_init(&qp->timerwait); - tasklet_hi_schedule(&qp->s_task); + qp->timer_next = rnr; + rnr = qp; + atomic_inc(&qp->refcount); if (list_empty(last)) break; qp = list_entry(last->next, struct ipath_qp, @@ -743,9 +736,13 @@ static void ipath_ib_timer(struct ipath_ibdev *dev) spin_unlock_irqrestore(&dev->pending_lock, flags); /* XXX What if timer fires again while this is running? */ - for (qp = resend; qp != NULL; qp = qp->timer_next) { + while (resend != NULL) { + qp = resend; + resend = qp->timer_next; + spin_lock_irqsave(&qp->s_lock, flags); - if (qp->s_last != qp->s_tail && qp->state == IB_QPS_RTS) { + if (qp->s_last != qp->s_tail && + ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK) { dev->n_timeouts++; ipath_restart_rc(qp, qp->s_last_psn + 1); } @@ -755,6 +752,19 @@ static void ipath_ib_timer(struct ipath_ibdev *dev) if (atomic_dec_and_test(&qp->refcount)) wake_up(&qp->wait); } + while (rnr != NULL) { + qp = rnr; + rnr = qp->timer_next; + + spin_lock_irqsave(&qp->s_lock, flags); + if (ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK) + ipath_schedule_send(qp); + spin_unlock_irqrestore(&qp->s_lock, flags); + + /* Notify ipath_destroy_qp() if it is waiting. */ + if (atomic_dec_and_test(&qp->refcount)) + wake_up(&qp->wait); + } } static void update_sge(struct ipath_sge_state *ss, u32 length) @@ -1010,13 +1020,24 @@ static void sdma_complete(void *cookie, int status) struct ipath_verbs_txreq *tx = cookie; struct ipath_qp *qp = tx->qp; struct ipath_ibdev *dev = to_idev(qp->ibqp.device); + unsigned int flags; + enum ib_wc_status ibs = status == IPATH_SDMA_TXREQ_S_OK ? + IB_WC_SUCCESS : IB_WC_WR_FLUSH_ERR; - /* Generate a completion queue entry if needed */ - if (qp->ibqp.qp_type != IB_QPT_RC && tx->wqe) { - enum ib_wc_status ibs = status == IPATH_SDMA_TXREQ_S_OK ? - IB_WC_SUCCESS : IB_WC_WR_FLUSH_ERR; - + if (atomic_dec_and_test(&qp->s_dma_busy)) { + spin_lock_irqsave(&qp->s_lock, flags); + if (tx->wqe) + ipath_send_complete(qp, tx->wqe, ibs); + if ((ib_ipath_state_ops[qp->state] & IPATH_FLUSH_SEND && + qp->s_last != qp->s_head) || + (qp->s_flags & IPATH_S_WAIT_DMA)) + ipath_schedule_send(qp); + spin_unlock_irqrestore(&qp->s_lock, flags); + wake_up(&qp->wait_dma); + } else if (tx->wqe) { + spin_lock_irqsave(&qp->s_lock, flags); ipath_send_complete(qp, tx->wqe, ibs); + spin_unlock_irqrestore(&qp->s_lock, flags); } if (tx->txreq.flags & IPATH_SDMA_TXREQ_F_FREEBUF) @@ -1027,6 +1048,21 @@ static void sdma_complete(void *cookie, int status) wake_up(&qp->wait); } +static void decrement_dma_busy(struct ipath_qp *qp) +{ + unsigned int flags; + + if (atomic_dec_and_test(&qp->s_dma_busy)) { + spin_lock_irqsave(&qp->s_lock, flags); + if ((ib_ipath_state_ops[qp->state] & IPATH_FLUSH_SEND && + qp->s_last != qp->s_head) || + (qp->s_flags & IPATH_S_WAIT_DMA)) + ipath_schedule_send(qp); + spin_unlock_irqrestore(&qp->s_lock, flags); + wake_up(&qp->wait_dma); + } +} + /* * Compute the number of clock cycles of delay before sending the next packet. * The multipliers reflect the number of clocks for the fastest rate so @@ -1065,9 +1101,12 @@ static int ipath_verbs_send_dma(struct ipath_qp *qp, if (tx) { qp->s_tx = NULL; /* resend previously constructed packet */ + atomic_inc(&qp->s_dma_busy); ret = ipath_sdma_verbs_send(dd, tx->ss, tx->len, tx); - if (ret) + if (ret) { qp->s_tx = tx; + decrement_dma_busy(qp); + } goto bail; } @@ -1118,12 +1157,14 @@ static int ipath_verbs_send_dma(struct ipath_qp *qp, tx->txreq.sg_count = ndesc; tx->map_len = (hdrwords + 2) << 2; tx->txreq.map_addr = &tx->hdr; + atomic_inc(&qp->s_dma_busy); ret = ipath_sdma_verbs_send(dd, ss, dwords, tx); if (ret) { /* save ss and length in dwords */ tx->ss = ss; tx->len = dwords; qp->s_tx = tx; + decrement_dma_busy(qp); } goto bail; } @@ -1144,6 +1185,7 @@ static int ipath_verbs_send_dma(struct ipath_qp *qp, memcpy(piobuf, hdr, hdrwords << 2); ipath_copy_from_sge(piobuf + hdrwords, ss, len); + atomic_inc(&qp->s_dma_busy); ret = ipath_sdma_verbs_send(dd, NULL, 0, tx); /* * If we couldn't queue the DMA request, save the info @@ -1154,6 +1196,7 @@ static int ipath_verbs_send_dma(struct ipath_qp *qp, tx->ss = NULL; tx->len = 0; qp->s_tx = tx; + decrement_dma_busy(qp); } dev->n_unaligned++; goto bail; @@ -1177,6 +1220,7 @@ static int ipath_verbs_send_pio(struct ipath_qp *qp, unsigned flush_wc; u32 control; int ret; + unsigned int flags; piobuf = ipath_getpiobuf(dd, plen, NULL); if (unlikely(piobuf == NULL)) { @@ -1247,8 +1291,11 @@ static int ipath_verbs_send_pio(struct ipath_qp *qp, } copy_io(piobuf, ss, len, flush_wc); done: - if (qp->s_wqe) + if (qp->s_wqe) { + spin_lock_irqsave(&qp->s_lock, flags); ipath_send_complete(qp, qp->s_wqe, IB_WC_SUCCESS); + spin_unlock_irqrestore(&qp->s_lock, flags); + } ret = 0; bail: return ret; @@ -1281,19 +1328,12 @@ int ipath_verbs_send(struct ipath_qp *qp, struct ipath_ib_header *hdr, * can defer SDMA restart until link goes ACTIVE without * worrying about just how we got there. */ - if (qp->ibqp.qp_type == IB_QPT_SMI) + if (qp->ibqp.qp_type == IB_QPT_SMI || + !(dd->ipath_flags & IPATH_HAS_SEND_DMA)) ret = ipath_verbs_send_pio(qp, hdr, hdrwords, ss, len, plen, dwords); - /* All non-VL15 packets are dropped if link is not ACTIVE */ - else if (!(dd->ipath_flags & IPATH_LINKACTIVE)) { - if (qp->s_wqe) - ipath_send_complete(qp, qp->s_wqe, IB_WC_SUCCESS); - ret = 0; - } else if (dd->ipath_flags & IPATH_HAS_SEND_DMA) - ret = ipath_verbs_send_dma(qp, hdr, hdrwords, ss, len, - plen, dwords); else - ret = ipath_verbs_send_pio(qp, hdr, hdrwords, ss, len, + ret = ipath_verbs_send_dma(qp, hdr, hdrwords, ss, len, plen, dwords); return ret; @@ -1401,27 +1441,46 @@ bail: * This is called from ipath_intr() at interrupt level when a PIO buffer is * available after ipath_verbs_send() returned an error that no buffers were * available. Return 1 if we consumed all the PIO buffers and we still have - * QPs waiting for buffers (for now, just do a tasklet_hi_schedule and + * QPs waiting for buffers (for now, just restart the send tasklet and * return zero). */ int ipath_ib_piobufavail(struct ipath_ibdev *dev) { + struct list_head *list; + struct ipath_qp *qplist; struct ipath_qp *qp; unsigned long flags; if (dev == NULL) goto bail; + list = &dev->piowait; + qplist = NULL; + spin_lock_irqsave(&dev->pending_lock, flags); - while (!list_empty(&dev->piowait)) { - qp = list_entry(dev->piowait.next, struct ipath_qp, - piowait); + while (!list_empty(list)) { + qp = list_entry(list->next, struct ipath_qp, piowait); list_del_init(&qp->piowait); - clear_bit(IPATH_S_BUSY, &qp->s_busy); - tasklet_hi_schedule(&qp->s_task); + qp->pio_next = qplist; + qplist = qp; + atomic_inc(&qp->refcount); } spin_unlock_irqrestore(&dev->pending_lock, flags); + while (qplist != NULL) { + qp = qplist; + qplist = qp->pio_next; + + spin_lock_irqsave(&qp->s_lock, flags); + if (ib_ipath_state_ops[qp->state] & IPATH_PROCESS_SEND_OK) + ipath_schedule_send(qp); + spin_unlock_irqrestore(&qp->s_lock, flags); + + /* Notify ipath_destroy_qp() if it is waiting. */ + if (atomic_dec_and_test(&qp->refcount)) + wake_up(&qp->wait); + } + bail: return 0; } @@ -2143,11 +2202,12 @@ bail: void ipath_unregister_ib_device(struct ipath_ibdev *dev) { struct ib_device *ibdev = &dev->ibdev; - - disable_timer(dev->dd); + u32 qps_inuse; ib_unregister_device(ibdev); + disable_timer(dev->dd); + if (!list_empty(&dev->pending[0]) || !list_empty(&dev->pending[1]) || !list_empty(&dev->pending[2])) @@ -2162,7 +2222,10 @@ void ipath_unregister_ib_device(struct ipath_ibdev *dev) * Note that ipath_unregister_ib_device() can be called before all * the QPs are destroyed! */ - ipath_free_all_qps(&dev->qp_table); + qps_inuse = ipath_free_all_qps(&dev->qp_table); + if (qps_inuse) + ipath_dev_err(dev->dd, "QP memory leak! %u still in use\n", + qps_inuse); kfree(dev->qp_table.table); kfree(dev->lk_table.table); kfree(dev->txreq_bufs); @@ -2213,17 +2276,14 @@ static ssize_t show_stats(struct device *device, struct device_attribute *attr, "RC OTH NAKs %d\n" "RC timeouts %d\n" "RC RDMA dup %d\n" - "RC stalls %d\n" "piobuf wait %d\n" - "no piobuf %d\n" "unaligned %d\n" "PKT drops %d\n" "WQE errs %d\n", dev->n_rc_resends, dev->n_rc_qacks, dev->n_rc_acks, dev->n_seq_naks, dev->n_rdma_seq, dev->n_rnr_naks, dev->n_other_naks, dev->n_timeouts, - dev->n_rdma_dup_busy, dev->n_rc_stalls, dev->n_piowait, - dev->n_no_piobuf, dev->n_unaligned, + dev->n_rdma_dup_busy, dev->n_piowait, dev->n_unaligned, dev->n_pkt_drops, dev->n_wqe_errs); for (i = 0; i < ARRAY_SIZE(dev->opstats); i++) { const struct ipath_opcode_stats *si = &dev->opstats[i]; diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h index 4c7c2aa8..deee02c 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.h +++ b/drivers/infiniband/hw/ipath/ipath_verbs.h @@ -74,6 +74,11 @@ #define IPATH_POST_RECV_OK 0x02 #define IPATH_PROCESS_RECV_OK 0x04 #define IPATH_PROCESS_SEND_OK 0x08 +#define IPATH_PROCESS_NEXT_SEND_OK 0x10 +#define IPATH_FLUSH_SEND 0x20 +#define IPATH_FLUSH_RECV 0x40 +#define IPATH_PROCESS_OR_FLUSH_SEND \ + (IPATH_PROCESS_SEND_OK | IPATH_FLUSH_SEND) /* IB Performance Manager status values */ #define IB_PMA_SAMPLE_STATUS_DONE 0x00 @@ -353,12 +358,14 @@ struct ipath_qp { struct ib_qp ibqp; struct ipath_qp *next; /* link list for QPN hash table */ struct ipath_qp *timer_next; /* link list for ipath_ib_timer() */ + struct ipath_qp *pio_next; /* link for ipath_ib_piobufavail() */ struct list_head piowait; /* link for wait PIO buf */ struct list_head timerwait; /* link for waiting for timeouts */ struct ib_ah_attr remote_ah_attr; struct ipath_ib_header s_hdr; /* next packet header to send */ atomic_t refcount; wait_queue_head_t wait; + wait_queue_head_t wait_dma; struct tasklet_struct s_task; struct ipath_mmap_info *ip; struct ipath_sge_state *s_cur_sge; @@ -369,7 +376,7 @@ struct ipath_qp { struct ipath_sge_state s_rdma_read_sge; struct ipath_sge_state r_sge; /* current receive data */ spinlock_t s_lock; - unsigned long s_busy; + atomic_t s_dma_busy; u16 s_pkt_delay; u16 s_hdrwords; /* size of s_hdr in 32 bit words */ u32 s_cur_size; /* size of send packet in bytes */ @@ -383,6 +390,7 @@ struct ipath_qp { u32 s_rnr_timeout; /* number of milliseconds for RNR timeout */ u32 r_ack_psn; /* PSN for next ACK or atomic ACK */ u64 r_wr_id; /* ID for current receive WQE */ + unsigned long r_aflags; u32 r_len; /* total length of r_sge */ u32 r_rcv_len; /* receive data len processed */ u32 r_psn; /* expected rcv packet sequence number */ @@ -394,8 +402,7 @@ struct ipath_qp { u8 r_state; /* opcode of last packet received */ u8 r_nak_state; /* non-zero if NAK is pending */ u8 r_min_rnr_timer; /* retry timeout value for RNR NAKs */ - u8 r_reuse_sge; /* for UC receive errors */ - u8 r_wrid_valid; /* r_wrid set but CQ entry not yet made */ + u8 r_flags; u8 r_max_rd_atomic; /* max number of RDMA read/atomic to receive */ u8 r_head_ack_queue; /* index into s_ack_queue[] */ u8 qp_access_flags; @@ -404,13 +411,13 @@ struct ipath_qp { u8 s_rnr_retry_cnt; u8 s_retry; /* requester retry counter */ u8 s_rnr_retry; /* requester RNR retry counter */ - u8 s_wait_credit; /* limit number of unacked packets sent */ u8 s_pkey_index; /* PKEY index to use */ u8 s_max_rd_atomic; /* max number of RDMA read/atomic to send */ u8 s_num_rd_atomic; /* number of RDMA read/atomic pending */ u8 s_tail_ack_queue; /* index into s_ack_queue[] */ u8 s_flags; u8 s_dmult; + u8 s_draining; u8 timeout; /* Timeout for this QP */ enum ib_mtu path_mtu; u32 remote_qpn; @@ -428,16 +435,39 @@ struct ipath_qp { struct ipath_sge r_sg_list[0]; /* verified SGEs */ }; -/* Bit definition for s_busy. */ -#define IPATH_S_BUSY 0 +/* + * Atomic bit definitions for r_aflags. + */ +#define IPATH_R_WRID_VALID 0 + +/* + * Bit definitions for r_flags. + */ +#define IPATH_R_REUSE_SGE 0x01 /* * Bit definitions for s_flags. + * + * IPATH_S_FENCE_PENDING - waiting for all prior RDMA read or atomic SWQEs + * before processing the next SWQE + * IPATH_S_RDMAR_PENDING - waiting for any RDMA read or atomic SWQEs + * before processing the next SWQE + * IPATH_S_WAITING - waiting for RNR timeout or send buffer available. + * IPATH_S_WAIT_SSN_CREDIT - waiting for RC credits to process next SWQE + * IPATH_S_WAIT_DMA - waiting for send DMA queue to drain before generating + * next send completion entry not via send DMA. */ #define IPATH_S_SIGNAL_REQ_WR 0x01 #define IPATH_S_FENCE_PENDING 0x02 #define IPATH_S_RDMAR_PENDING 0x04 #define IPATH_S_ACK_PENDING 0x08 +#define IPATH_S_BUSY 0x10 +#define IPATH_S_WAITING 0x20 +#define IPATH_S_WAIT_SSN_CREDIT 0x40 +#define IPATH_S_WAIT_DMA 0x80 + +#define IPATH_S_ANY_WAIT (IPATH_S_FENCE_PENDING | IPATH_S_RDMAR_PENDING | \ + IPATH_S_WAITING | IPATH_S_WAIT_SSN_CREDIT | IPATH_S_WAIT_DMA) #define IPATH_PSN_CREDIT 512 @@ -573,13 +603,11 @@ struct ipath_ibdev { u32 n_rnr_naks; u32 n_other_naks; u32 n_timeouts; - u32 n_rc_stalls; u32 n_pkt_drops; u32 n_vl15_dropped; u32 n_wqe_errs; u32 n_rdma_dup_busy; u32 n_piowait; - u32 n_no_piobuf; u32 n_unaligned; u32 port_cap_flags; u32 pma_sample_start; @@ -657,6 +685,17 @@ static inline struct ipath_ibdev *to_idev(struct ib_device *ibdev) return container_of(ibdev, struct ipath_ibdev, ibdev); } +/* + * This must be called with s_lock held. + */ +static inline void ipath_schedule_send(struct ipath_qp *qp) +{ + if (qp->s_flags & IPATH_S_ANY_WAIT) + qp->s_flags &= ~IPATH_S_ANY_WAIT; + if (!(qp->s_flags & IPATH_S_BUSY)) + tasklet_hi_schedule(&qp->s_task); +} + int ipath_process_mad(struct ib_device *ibdev, int mad_flags, u8 port_num, @@ -706,7 +745,7 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int ipath_query_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask, struct ib_qp_init_attr *init_attr); -void ipath_free_all_qps(struct ipath_qp_table *qpt); +unsigned ipath_free_all_qps(struct ipath_qp_table *qpt); int ipath_init_qp_table(struct ipath_ibdev *idev, int size); -- cgit v1.1 From 74116f580b7279543340dd716a2af642f5c1c2c7 Mon Sep 17 00:00:00 2001 From: Ralph Campbell Date: Tue, 13 May 2008 11:42:20 -0700 Subject: IB/ipath: Fix RDMA read response sequence checking If an out of sequence RDMA read response middle or last packet is received, we should only resend the RDMA read request on the first out of sequence packet and drop subsequent out of sequence packets otherwise, we get "too many retries". Signed-off-by: Ralph Campbell Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_rc.c | 7 +++++++ drivers/infiniband/hw/ipath/ipath_verbs.h | 1 + 2 files changed, 8 insertions(+) diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index 5b5276a..108df66 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c @@ -1189,6 +1189,7 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, wqe = get_swqe_ptr(qp, qp->s_last); if (unlikely(wqe->wr.opcode != IB_WR_RDMA_READ)) goto ack_op_err; + qp->r_flags &= ~IPATH_R_RDMAR_SEQ; /* * If this is a response to a resent RDMA read, we * have to be careful to copy the data to the right @@ -1202,6 +1203,9 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, /* no AETH, no ACK */ if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) { dev->n_rdma_seq++; + if (qp->r_flags & IPATH_R_RDMAR_SEQ) + goto ack_done; + qp->r_flags |= IPATH_R_RDMAR_SEQ; ipath_restart_rc(qp, qp->s_last_psn + 1); goto ack_done; } @@ -1263,6 +1267,9 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, /* ACKs READ req. */ if (unlikely(ipath_cmp24(psn, qp->s_last_psn + 1))) { dev->n_rdma_seq++; + if (qp->r_flags & IPATH_R_RDMAR_SEQ) + goto ack_done; + qp->r_flags |= IPATH_R_RDMAR_SEQ; ipath_restart_rc(qp, qp->s_last_psn + 1); goto ack_done; } diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.h b/drivers/infiniband/hw/ipath/ipath_verbs.h index deee02c..9d12ae8 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.h +++ b/drivers/infiniband/hw/ipath/ipath_verbs.h @@ -444,6 +444,7 @@ struct ipath_qp { * Bit definitions for r_flags. */ #define IPATH_R_REUSE_SGE 0x01 +#define IPATH_R_RDMAR_SEQ 0x02 /* * Bit definitions for s_flags. -- cgit v1.1 From 40d97692fbfe52ef68fa771d8121394b2210fd67 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 13 May 2008 11:45:32 -0700 Subject: IB/ipath: Make ipath_portdata work with struct pid * not pid_t The official reason is "with the presence of pid namespaces in the kernel using pid_t-s inside one is no longer safe." But the reason I fix this right now is the following: About a month ago (when 2.6.25 was not yet released) there still was a one last caller of a to-be-deprecated-soon function find_pid() - the kill_proc() function, which in turn was only used by nfs callback code. During the last merge window, this last caller was finally eliminated by some NFS patch(es) and I was about to finally kill this kill_proc() and find_pid(), but found, that I was late and the kill_proc is now called from the ipath driver since commit 58411d1c ("IB/ipath: Head of Line blocking vs forward progress of user apps"). So here's a patch that fixes this code to use struct pid * and (!) the kill_pid routine. Signed-off-by: Pavel Emelyanov Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_driver.c | 18 ++++++++++-------- drivers/infiniband/hw/ipath/ipath_file_ops.c | 19 +++++++++++-------- drivers/infiniband/hw/ipath/ipath_kernel.h | 4 ++-- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index ce7b7c3..258e66c 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c @@ -2616,7 +2616,7 @@ int ipath_reset_device(int unit) ipath_dbg("unit %u port %d is in use " "(PID %u cmd %s), can't reset\n", unit, i, - dd->ipath_pd[i]->port_pid, + pid_nr(dd->ipath_pd[i]->port_pid), dd->ipath_pd[i]->port_comm); ret = -EBUSY; goto bail; @@ -2654,19 +2654,21 @@ bail: static int ipath_signal_procs(struct ipath_devdata *dd, int sig) { int i, sub, any = 0; - pid_t pid; + struct pid *pid; if (!dd->ipath_pd) return 0; for (i = 1; i < dd->ipath_cfgports; i++) { - if (!dd->ipath_pd[i] || !dd->ipath_pd[i]->port_cnt || - !dd->ipath_pd[i]->port_pid) + if (!dd->ipath_pd[i] || !dd->ipath_pd[i]->port_cnt) continue; pid = dd->ipath_pd[i]->port_pid; + if (!pid) + continue; + dev_info(&dd->pcidev->dev, "context %d in use " "(PID %u), sending signal %d\n", - i, pid, sig); - kill_proc(pid, sig, 1); + i, pid_nr(pid), sig); + kill_pid(pid, sig, 1); any++; for (sub = 0; sub < INFINIPATH_MAX_SUBPORT; sub++) { pid = dd->ipath_pd[i]->port_subpid[sub]; @@ -2674,8 +2676,8 @@ static int ipath_signal_procs(struct ipath_devdata *dd, int sig) continue; dev_info(&dd->pcidev->dev, "sub-context " "%d:%d in use (PID %u), sending " - "signal %d\n", i, sub, pid, sig); - kill_proc(pid, sig, 1); + "signal %d\n", i, sub, pid_nr(pid), sig); + kill_pid(pid, sig, 1); any++; } } diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index 3295177..b472b15 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c @@ -555,7 +555,7 @@ static int ipath_tid_free(struct ipath_portdata *pd, unsigned subport, p = dd->ipath_pageshadow[porttid + tid]; dd->ipath_pageshadow[porttid + tid] = NULL; ipath_cdbg(VERBOSE, "PID %u freeing TID %u\n", - pd->port_pid, tid); + pid_nr(pd->port_pid), tid); dd->ipath_f_put_tid(dd, &tidbase[tid], RCVHQ_RCV_TYPE_EXPECTED, dd->ipath_tidinvalid); @@ -1609,7 +1609,7 @@ static int try_alloc_port(struct ipath_devdata *dd, int port, port); pd->port_cnt = 1; port_fp(fp) = pd; - pd->port_pid = current->pid; + pd->port_pid = get_pid(task_pid(current)); strncpy(pd->port_comm, current->comm, sizeof(pd->port_comm)); ipath_stats.sps_ports++; ret = 0; @@ -1793,14 +1793,15 @@ static int find_shared_port(struct file *fp, } port_fp(fp) = pd; subport_fp(fp) = pd->port_cnt++; - pd->port_subpid[subport_fp(fp)] = current->pid; + pd->port_subpid[subport_fp(fp)] = + get_pid(task_pid(current)); tidcursor_fp(fp) = 0; pd->active_slaves |= 1 << subport_fp(fp); ipath_cdbg(PROC, "%s[%u] %u sharing %s[%u] unit:port %u:%u\n", current->comm, current->pid, subport_fp(fp), - pd->port_comm, pd->port_pid, + pd->port_comm, pid_nr(pd->port_pid), dd->ipath_unit, pd->port_port); ret = 1; goto done; @@ -2066,7 +2067,8 @@ static int ipath_close(struct inode *in, struct file *fp) * the slave(s) don't wait for receive data forever. */ pd->active_slaves &= ~(1 << fd->subport); - pd->port_subpid[fd->subport] = 0; + put_pid(pd->port_subpid[fd->subport]); + pd->port_subpid[fd->subport] = NULL; mutex_unlock(&ipath_mutex); goto bail; } @@ -2074,7 +2076,7 @@ static int ipath_close(struct inode *in, struct file *fp) if (pd->port_hdrqfull) { ipath_cdbg(PROC, "%s[%u] had %u rcvhdrqfull errors " - "during run\n", pd->port_comm, pd->port_pid, + "during run\n", pd->port_comm, pid_nr(pd->port_pid), pd->port_hdrqfull); pd->port_hdrqfull = 0; } @@ -2134,11 +2136,12 @@ static int ipath_close(struct inode *in, struct file *fp) unlock_expected_tids(pd); ipath_stats.sps_ports--; ipath_cdbg(PROC, "%s[%u] closed port %u:%u\n", - pd->port_comm, pd->port_pid, + pd->port_comm, pid_nr(pd->port_pid), dd->ipath_unit, port); } - pd->port_pid = 0; + put_pid(pd->port_pid); + pd->port_pid = NULL; dd->ipath_pd[pd->port_port] = NULL; /* before releasing mutex */ mutex_unlock(&ipath_mutex); ipath_free_pddata(dd, pd); /* after releasing the mutex */ diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 02b24a3..2097587 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h @@ -159,8 +159,8 @@ struct ipath_portdata { /* saved total number of polled urgent packets for poll edge trigger */ u32 port_urgent_poll; /* pid of process using this port */ - pid_t port_pid; - pid_t port_subpid[INFINIPATH_MAX_SUBPORT]; + struct pid *port_pid; + struct pid *port_subpid[INFINIPATH_MAX_SUBPORT]; /* same size as task_struct .comm[] */ char port_comm[16]; /* pkeys set by this use of this port */ -- cgit v1.1 From f018c7e177a50390f6fcb137f1a28a6027d8ba50 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 13 May 2008 11:51:23 -0700 Subject: IB/ipath: Change ipath_devdata.ipath_sdma_status to be unsigned long Andrew Morton pointed out that bitops should take an unsigned long * arg. However, the ipath driver was doing bitops on struct ipath_devdata.ipath_sdma_status, which is u64. Change this member to unsigned long to avoid tons of warnings when x86 fixes the bitops to take unsigned long * instead of void *. Also, change the IPATH_SDMA_RUNNING and IPATH_SDMA_SHUTDOWN bit numbers to 30 and 31 (instead of 62 and 63) so that we're not setting another booby trap for someone who tries to make ipath work on a 32-bit architecture. Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_driver.c | 2 +- drivers/infiniband/hw/ipath/ipath_kernel.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 258e66c..daad09a 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c @@ -1894,7 +1894,7 @@ void ipath_cancel_sends(struct ipath_devdata *dd, int restore_sendctrl) */ if (dd->ipath_flags & IPATH_HAS_SEND_DMA) { int skip_cancel; - u64 *statp = &dd->ipath_sdma_status; + unsigned long *statp = &dd->ipath_sdma_status; spin_lock_irqsave(&dd->ipath_sdma_lock, flags); skip_cancel = diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index 2097587..59a8b25 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h @@ -483,7 +483,7 @@ struct ipath_devdata { /* SendDMA related entries */ spinlock_t ipath_sdma_lock; - u64 ipath_sdma_status; + unsigned long ipath_sdma_status; unsigned long ipath_sdma_abort_jiffies; unsigned long ipath_sdma_abort_intr_timeout; unsigned long ipath_sdma_buf_jiffies; @@ -822,8 +822,8 @@ struct ipath_devdata { #define IPATH_SDMA_DISARMED 1 #define IPATH_SDMA_DISABLED 2 #define IPATH_SDMA_LAYERBUF 3 -#define IPATH_SDMA_RUNNING 62 -#define IPATH_SDMA_SHUTDOWN 63 +#define IPATH_SDMA_RUNNING 30 +#define IPATH_SDMA_SHUTDOWN 31 /* bit combinations that correspond to abort states */ #define IPATH_SDMA_ABORT_NONE 0 -- cgit v1.1 From a58e58fafdff4c25949221e46132e86f709d0b79 Mon Sep 17 00:00:00 2001 From: Steve Wise Date: Tue, 13 May 2008 11:52:55 -0700 Subject: RDMA/cxgb3: Wrap the software send queue pointer as needed on flush cxio_flush_sq() was failing to wrap around the software send queue causing garbage completion entries on a flush operation. Signed-off-by: Steve Wise Signed-off-by: Roland Dreier --- drivers/infiniband/hw/cxgb3/cxio_hal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/infiniband/hw/cxgb3/cxio_hal.c b/drivers/infiniband/hw/cxgb3/cxio_hal.c index ebf9d30..3f441fc 100644 --- a/drivers/infiniband/hw/cxgb3/cxio_hal.c +++ b/drivers/infiniband/hw/cxgb3/cxio_hal.c @@ -405,11 +405,11 @@ int cxio_flush_sq(struct t3_wq *wq, struct t3_cq *cq, int count) struct t3_swsq *sqp = wq->sq + Q_PTR2IDX(wq->sq_rptr, wq->sq_size_log2); ptr = wq->sq_rptr + count; - sqp += count; + sqp = wq->sq + Q_PTR2IDX(ptr, wq->sq_size_log2); while (ptr != wq->sq_wptr) { insert_sq_cqe(wq, cq, sqp); - sqp++; ptr++; + sqp = wq->sq + Q_PTR2IDX(ptr, wq->sq_size_log2); flushed++; } return flushed; -- cgit v1.1 From dfc5d03f12e706c19ee37734184ea96582ef931d Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 13 May 2008 19:11:51 -0400 Subject: ext4: correct mount option parsing to detect when quota options can be changed We should not allow user to change quota mount options when quota is just suspended. It would make mount options and internal quota state inconsistent. Also we should not allow user to change quota format when quota is turned on. On the other hand we can just silently ignore when some option is set to the value it already has (mount does this on remount). Cc: Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Mingming Cao Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 52dd067..686ebcc 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -979,7 +979,7 @@ static int parse_options (char *options, struct super_block *sb, int data_opt = 0; int option; #ifdef CONFIG_QUOTA - int qtype; + int qtype, qfmt; char *qname; #endif @@ -1162,7 +1162,9 @@ static int parse_options (char *options, struct super_block *sb, case Opt_grpjquota: qtype = GRPQUOTA; set_qf_name: - if (sb_any_quota_enabled(sb)) { + if ((sb_any_quota_enabled(sb) || + sb_any_quota_suspended(sb)) && + !sbi->s_qf_names[qtype]) { printk(KERN_ERR "EXT4-fs: Cannot change journalled " "quota options when quota turned on.\n"); @@ -1200,7 +1202,9 @@ set_qf_name: case Opt_offgrpjquota: qtype = GRPQUOTA; clear_qf_name: - if (sb_any_quota_enabled(sb)) { + if ((sb_any_quota_enabled(sb) || + sb_any_quota_suspended(sb)) && + sbi->s_qf_names[qtype]) { printk(KERN_ERR "EXT4-fs: Cannot change " "journalled quota options when " "quota turned on.\n"); @@ -1213,10 +1217,20 @@ clear_qf_name: sbi->s_qf_names[qtype] = NULL; break; case Opt_jqfmt_vfsold: - sbi->s_jquota_fmt = QFMT_VFS_OLD; - break; + qfmt = QFMT_VFS_OLD; + goto set_qf_format; case Opt_jqfmt_vfsv0: - sbi->s_jquota_fmt = QFMT_VFS_V0; + qfmt = QFMT_VFS_V0; +set_qf_format: + if ((sb_any_quota_enabled(sb) || + sb_any_quota_suspended(sb)) && + sbi->s_jquota_fmt != qfmt) { + printk(KERN_ERR "EXT4-fs: Cannot change " + "journaled quota options when " + "quota turned on.\n"); + return 0; + } + sbi->s_jquota_fmt = qfmt; break; case Opt_quota: case Opt_usrquota: -- cgit v1.1 From cd59e7b9781a35716b8a3e8c4aa2d48081d7daf7 Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 13 May 2008 19:11:51 -0400 Subject: ext4: Fix mount messages when quota disabled When quota is disabled, we should not print 'journaled quota not supported' when user tried to mount non-journaled quota. Also fix typo in the message. Signed-off-by: Jan Kara Signed-off-by: Mingming Cao Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 686ebcc..94a5272 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1255,6 +1255,9 @@ set_qf_format: case Opt_quota: case Opt_usrquota: case Opt_grpquota: + printk(KERN_ERR + "EXT4-fs: quota options not supported.\n"); + break; case Opt_usrjquota: case Opt_grpjquota: case Opt_offusrjquota: @@ -1262,7 +1265,7 @@ set_qf_format: case Opt_jqfmt_vfsold: case Opt_jqfmt_vfsv0: printk(KERN_ERR - "EXT4-fs: journalled quota options not " + "EXT4-fs: journaled quota options not " "supported.\n"); break; case Opt_noquota: -- cgit v1.1 From 0623543b3335c8e439cacf21af99bbf45da42c5a Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 13 May 2008 19:11:51 -0400 Subject: ext4: fix synchronization of quota files in journal=data mode In journal=data mode, it is not enough to do write_inode_now as done in vfs_quota_on() to write all data to their final location (which is needed for quota_read to work correctly). Calling journal_flush() does its job. Cc: Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Mingming Cao Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 94a5272..cddf7f0 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -3170,23 +3170,42 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, if (!test_opt(sb, QUOTA)) return -EINVAL; - /* Not journalling quota? */ - if ((!EXT4_SB(sb)->s_qf_names[USRQUOTA] && - !EXT4_SB(sb)->s_qf_names[GRPQUOTA]) || remount) + /* When remounting, no checks are needed and in fact, path is NULL */ + if (remount) return vfs_quota_on(sb, type, format_id, path, remount); + err = path_lookup(path, LOOKUP_FOLLOW, &nd); if (err) return err; + /* Quotafile not on the same filesystem? */ if (nd.path.mnt->mnt_sb != sb) { path_put(&nd.path); return -EXDEV; } - /* Quotafile not of fs root? */ - if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode) - printk(KERN_WARNING - "EXT4-fs: Quota file not on filesystem root. " - "Journalled quota will not work.\n"); + /* Journaling quota? */ + if (EXT4_SB(sb)->s_qf_names[type]) { + /* Quotafile not of fs root? */ + if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode) + printk(KERN_WARNING + "EXT4-fs: Quota file not on filesystem root. " + "Journaled quota will not work.\n"); + } + + /* + * When we journal data on quota file, we have to flush journal to see + * all updates to the file when we bypass pagecache... + */ + if (ext4_should_journal_data(nd.path.dentry->d_inode)) { + /* + * We don't need to lock updates but journal_flush() could + * otherwise be livelocked... + */ + jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); + jbd2_journal_flush(EXT4_SB(sb)->s_journal); + jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); + } + path_put(&nd.path); return vfs_quota_on(sb, type, format_id, path, remount); } -- cgit v1.1 From 2c8be6b222f76c332d9faeb00c047996d340632c Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Tue, 13 May 2008 21:27:55 -0400 Subject: ext4: fix typos in messages and comments (journalled -> journaled) Cc: Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Mingming Cao Signed-off-by: "Theodore Ts'o" --- fs/ext4/super.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/fs/ext4/super.c b/fs/ext4/super.c index cddf7f0..09d9359 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -1166,7 +1166,7 @@ set_qf_name: sb_any_quota_suspended(sb)) && !sbi->s_qf_names[qtype]) { printk(KERN_ERR - "EXT4-fs: Cannot change journalled " + "EXT4-fs: Cannot change journaled " "quota options when quota turned on.\n"); return 0; } @@ -1206,7 +1206,7 @@ clear_qf_name: sb_any_quota_suspended(sb)) && sbi->s_qf_names[qtype]) { printk(KERN_ERR "EXT4-fs: Cannot change " - "journalled quota options when " + "journaled quota options when " "quota turned on.\n"); return 0; } @@ -1350,14 +1350,14 @@ set_qf_format: } if (!sbi->s_jquota_fmt) { - printk(KERN_ERR "EXT4-fs: journalled quota format " + printk(KERN_ERR "EXT4-fs: journaled quota format " "not specified.\n"); return 0; } } else { if (sbi->s_jquota_fmt) { - printk(KERN_ERR "EXT4-fs: journalled quota format " - "specified with no journalling " + printk(KERN_ERR "EXT4-fs: journaled quota format " + "specified with no journaling " "enabled.\n"); return 0; } @@ -1598,7 +1598,7 @@ static void ext4_orphan_cleanup (struct super_block * sb, int ret = ext4_quota_on_mount(sb, i); if (ret < 0) printk(KERN_ERR - "EXT4-fs: Cannot turn on journalled " + "EXT4-fs: Cannot turn on journaled " "quota: error %d\n", ret); } } @@ -3123,7 +3123,7 @@ static int ext4_release_dquot(struct dquot *dquot) static int ext4_mark_dquot_dirty(struct dquot *dquot) { - /* Are we journalling quotas? */ + /* Are we journaling quotas? */ if (EXT4_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] || EXT4_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) { dquot_mark_dquot_dirty(dquot); -- cgit v1.1 From 1930479c4b6bbcb6f164a5b3498e0d98329967f4 Mon Sep 17 00:00:00 2001 From: Valerie Clement Date: Tue, 13 May 2008 19:31:14 -0400 Subject: ext4: mballoc fix mb_normalize_request algorithm for 1KB block size filesystems In case of inode preallocation, the number of blocks to allocate depends on the file size and it is calculated in ext4_mb_normalize_request(). Each group in the filesystem is then checked to find one that can be used for allocation; this is done in ext4_mb_good_group(). When a file bigger than 4MB is created, the requested number of blocks to preallocate, calculated by ext4_mb_normalize_request is 4096. However for a filesystem with 1KB block size, the maximum size of the block buddies used by the multiblock allocator is 2048, so none of groups in the filesystem satisfies the search criteria in ext4_mb_good_group(). Scanning all the filesystem groups impacts performance. This was demonstrated by using a freshly created, 70GB, 1k block filesystem, with caches dropped write before the test via /proc/sys/vm/drop_caches, and with the filesystem mounted with nodelalloc and nodealloc,nomballoc. The time to write an 8 megabyte file using "dd if=/dev/zero of=/mnt/test/fo bs=8k count=1k conv=fsync" took 35.5091 seconds (236kB/s) with nodellaloc, and 0.233754 seconds (35.9 MB/s) with the nodelloc,nomballoc options. With a 1TB partition, it took several minutes to write 8MB! This patch modifies the algorithm in ext4_mb_normalize_group_request to calculate the number of blocks to allocate by taking into account the maximum size of free blocks chunks handled by the multiblock allocator. It has also been tested for filesystems with 2KB and 4KB block sizes to ensure that those cases don't regress. Reviewed-by: Aneesh Kumar K.V Signed-off-by: Valerie Clement Signed-off-by: Mingming Cao Signed-off-by: "Theodore Ts'o" --- fs/ext4/mballoc.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index b128bdc..1d7fde9 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -2880,12 +2880,11 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, if (size < i_size_read(ac->ac_inode)) size = i_size_read(ac->ac_inode); - /* max available blocks in a free group */ - max = EXT4_BLOCKS_PER_GROUP(ac->ac_sb) - 1 - 1 - - EXT4_SB(ac->ac_sb)->s_itb_per_group; + /* max size of free chunks */ + max = 2 << bsbits; -#define NRL_CHECK_SIZE(req, size, max,bits) \ - (req <= (size) || max <= ((size) >> bits)) +#define NRL_CHECK_SIZE(req, size, max, chunk_size) \ + (req <= (size) || max <= (chunk_size)) /* first, try to predict filesize */ /* XXX: should this table be tunable? */ @@ -2904,16 +2903,16 @@ ext4_mb_normalize_request(struct ext4_allocation_context *ac, size = 512 * 1024; } else if (size <= 1024 * 1024) { size = 1024 * 1024; - } else if (NRL_CHECK_SIZE(size, 4 * 1024 * 1024, max, bsbits)) { + } else if (NRL_CHECK_SIZE(size, 4 * 1024 * 1024, max, 2 * 1024)) { start_off = ((loff_t)ac->ac_o_ex.fe_logical >> - (20 - bsbits)) << 20; - size = 1024 * 1024; - } else if (NRL_CHECK_SIZE(size, 8 * 1024 * 1024, max, bsbits)) { + (21 - bsbits)) << 21; + size = 2 * 1024 * 1024; + } else if (NRL_CHECK_SIZE(size, 8 * 1024 * 1024, max, 4 * 1024)) { start_off = ((loff_t)ac->ac_o_ex.fe_logical >> (22 - bsbits)) << 22; size = 4 * 1024 * 1024; } else if (NRL_CHECK_SIZE(ac->ac_o_ex.fe_len, - (8<<20)>>bsbits, max, bsbits)) { + (8<<20)>>bsbits, max, 8 * 1024)) { start_off = ((loff_t)ac->ac_o_ex.fe_logical >> (23 - bsbits)) << 23; size = 8 * 1024 * 1024; -- cgit v1.1 From a1355e530173021099d0401f3294414382189dbd Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 30 Apr 2008 11:40:17 -0300 Subject: V4L/DVB (7800): tuner_symbol_probe(): don't do symbol_put() if symbol_request() failed Because it goes BUG. Signed-off-by: Andrew Morton Acked-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 6bf104e..c8cd718 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -40,11 +40,11 @@ typeof(&FUNCTION) __a = symbol_request(FUNCTION); \ if (__a) { \ __r = (int) __a(ARGS); \ + symbol_put(FUNCTION); \ } else { \ printk(KERN_ERR "TUNER: Unable to find " \ "symbol "#FUNCTION"()\n"); \ } \ - symbol_put(FUNCTION); \ __r; \ }) -- cgit v1.1 From d557dab5de82edfe5bab9a1964dfc5cf2b2b6833 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Apr 2008 15:27:55 -0300 Subject: V4L/DVB (7801): saa7134: detach frontend, if tuner or Diseqc attach fails Before this patch, an error at tuner or diseqc were discarded by the driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-dvb.c | 141 +++++++++++++++++++++--------- 1 file changed, 101 insertions(+), 40 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 2d16be2..2a9aa72 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -538,19 +538,23 @@ static int philips_tda827x_tuner_sleep(struct dvb_frontend *fe) return 0; } -static void configure_tda827x_fe(struct saa7134_dev *dev, struct tda1004x_config *cdec_conf, - struct tda827x_config *tuner_conf) +static int configure_tda827x_fe(struct saa7134_dev *dev, + struct tda1004x_config *cdec_conf, + struct tda827x_config *tuner_conf) { dev->dvb.frontend = dvb_attach(tda10046_attach, cdec_conf, &dev->i2c_adap); if (dev->dvb.frontend) { if (cdec_conf->i2c_gate) dev->dvb.frontend->ops.i2c_gate_ctrl = tda8290_i2c_gate_ctrl; - if (dvb_attach(tda827x_attach, dev->dvb.frontend, cdec_conf->tuner_address, - &dev->i2c_adap, tuner_conf) == NULL) { - wprintk("no tda827x tuner found at addr: %02x\n", + if (dvb_attach(tda827x_attach, dev->dvb.frontend, + cdec_conf->tuner_address, + &dev->i2c_adap, tuner_conf)) + return 0; + + wprintk("no tda827x tuner found at addr: %02x\n", cdec_conf->tuner_address); - } } + return -EINVAL; } /* ------------------------------------------------------------------ */ @@ -997,7 +1001,9 @@ static int dvb_init(struct saa7134_dev *dev) break; case SAA7134_BOARD_FLYDVBTDUO: case SAA7134_BOARD_FLYDVBT_DUO_CARDBUS: - configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0); + if (configure_tda827x_fe(dev, &tda827x_lifeview_config, + &tda827x_cfg_0) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_PHILIPS_EUROPA: case SAA7134_BOARD_VIDEOMATE_DVBT_300: @@ -1022,36 +1028,52 @@ static int dvb_init(struct saa7134_dev *dev) } break; case SAA7134_BOARD_KWORLD_DVBT_210: - configure_tda827x_fe(dev, &kworld_dvb_t_210_config, &tda827x_cfg_2); + if (configure_tda827x_fe(dev, &kworld_dvb_t_210_config, + &tda827x_cfg_2) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_PHILIPS_TIGER: - configure_tda827x_fe(dev, &philips_tiger_config, &tda827x_cfg_0); + if (configure_tda827x_fe(dev, &philips_tiger_config, + &tda827x_cfg_0) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_PINNACLE_PCTV_310i: - configure_tda827x_fe(dev, &pinnacle_pctv_310i_config, &tda827x_cfg_1); + if (configure_tda827x_fe(dev, &pinnacle_pctv_310i_config, + &tda827x_cfg_1) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_HAUPPAUGE_HVR1110: - configure_tda827x_fe(dev, &hauppauge_hvr_1110_config, &tda827x_cfg_1); + if (configure_tda827x_fe(dev, &hauppauge_hvr_1110_config, + &tda827x_cfg_1) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_ASUSTeK_P7131_DUAL: - configure_tda827x_fe(dev, &asus_p7131_dual_config, &tda827x_cfg_0); + if (configure_tda827x_fe(dev, &asus_p7131_dual_config, + &tda827x_cfg_0) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_FLYDVBT_LR301: - configure_tda827x_fe(dev, &tda827x_lifeview_config, &tda827x_cfg_0); + if (configure_tda827x_fe(dev, &tda827x_lifeview_config, + &tda827x_cfg_0) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_FLYDVB_TRIO: - if(! use_frontend) { /* terrestrial */ - configure_tda827x_fe(dev, &lifeview_trio_config, &tda827x_cfg_0); + if (!use_frontend) { /* terrestrial */ + if (configure_tda827x_fe(dev, &lifeview_trio_config, + &tda827x_cfg_0) < 0) + goto dettach_frontend; } else { /* satellite */ dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); if (dev->dvb.frontend) { if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x63, &dev->i2c_adap, 0) == NULL) { wprintk("%s: Lifeview Trio, No tda826x found!\n", __func__); + goto dettach_frontend; } if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap, 0x08, 0, 0) == NULL) { wprintk("%s: Lifeview Trio, No ISL6421 found!\n", __func__); + goto dettach_frontend; } } } @@ -1067,15 +1089,20 @@ static int dvb_init(struct saa7134_dev *dev) &ads_duo_cfg) == NULL) { wprintk("no tda827x tuner found at addr: %02x\n", ads_tech_duo_config.tuner_address); + goto dettach_frontend; } } break; case SAA7134_BOARD_TEVION_DVBT_220RF: - configure_tda827x_fe(dev, &tevion_dvbt220rf_config, &tda827x_cfg_0); + if (configure_tda827x_fe(dev, &tevion_dvbt220rf_config, + &tda827x_cfg_0) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_MEDION_MD8800_QUADRO: if (!use_frontend) { /* terrestrial */ - configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0); + if (configure_tda827x_fe(dev, &md8800_dvbt_config, + &tda827x_cfg_0) < 0) + goto dettach_frontend; } else { /* satellite */ dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); @@ -1086,16 +1113,20 @@ static int dvb_init(struct saa7134_dev *dev) struct i2c_msg msg = {.addr = 0x08, .flags = 0, .len = 1}; if (dvb_attach(tda826x_attach, dev->dvb.frontend, - 0x60, &dev->i2c_adap, 0) == NULL) + 0x60, &dev->i2c_adap, 0) == NULL) { wprintk("%s: Medion Quadro, no tda826x " "found !\n", __func__); + goto dettach_frontend; + } if (dev_id != 0x08) { /* we need to open the i2c gate (we know it exists) */ fe->ops.i2c_gate_ctrl(fe, 1); if (dvb_attach(isl6405_attach, fe, - &dev->i2c_adap, 0x08, 0, 0) == NULL) + &dev->i2c_adap, 0x08, 0, 0) == NULL) { wprintk("%s: Medion Quadro, no ISL6405 " "found !\n", __func__); + goto dettach_frontend; + } if (dev_id == 0x07) { /* fire up the 2nd section of the LNB supply since we can't do this from the other section */ @@ -1117,19 +1148,17 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180: dev->dvb.frontend = dvb_attach(nxt200x_attach, &avertvhda180, &dev->i2c_adap); - if (dev->dvb.frontend) { + if (dev->dvb.frontend) dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, NULL, DVB_PLL_TDHU2); - } break; case SAA7134_BOARD_KWORLD_ATSC110: dev->dvb.frontend = dvb_attach(nxt200x_attach, &kworldatsc110, &dev->i2c_adap); - if (dev->dvb.frontend) { + if (dev->dvb.frontend) dvb_attach(simple_tuner_attach, dev->dvb.frontend, &dev->i2c_adap, 0x61, TUNER_PHILIPS_TUV1236D); - } break; case SAA7134_BOARD_FLYDVBS_LR300: dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, @@ -1138,10 +1167,12 @@ static int dvb_init(struct saa7134_dev *dev) if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, &dev->i2c_adap, 0) == NULL) { wprintk("%s: No tda826x found!\n", __func__); + goto dettach_frontend; } if (dvb_attach(isl6421_attach, dev->dvb.frontend, &dev->i2c_adap, 0x08, 0, 0) == NULL) { wprintk("%s: No ISL6421 found!\n", __func__); + goto dettach_frontend; } } break; @@ -1168,43 +1199,65 @@ static int dvb_init(struct saa7134_dev *dev) } break; case SAA7134_BOARD_CINERGY_HT_PCMCIA: - configure_tda827x_fe(dev, &cinergy_ht_config, &tda827x_cfg_0); + if (configure_tda827x_fe(dev, &cinergy_ht_config, + &tda827x_cfg_0) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_CINERGY_HT_PCI: - configure_tda827x_fe(dev, &cinergy_ht_pci_config, &tda827x_cfg_0); + if (configure_tda827x_fe(dev, &cinergy_ht_pci_config, + &tda827x_cfg_0) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_PHILIPS_TIGER_S: - configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2); + if (configure_tda827x_fe(dev, &philips_tiger_s_config, + &tda827x_cfg_2) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_ASUS_P7131_4871: - configure_tda827x_fe(dev, &asus_p7131_4871_config, &tda827x_cfg_2); + if (configure_tda827x_fe(dev, &asus_p7131_4871_config, + &tda827x_cfg_2) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_ASUSTeK_P7131_HYBRID_LNA: - configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config, &tda827x_cfg_2); + if (configure_tda827x_fe(dev, &asus_p7131_hybrid_lna_config, + &tda827x_cfg_2) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_AVERMEDIA_SUPER_007: - configure_tda827x_fe(dev, &avermedia_super_007_config, &tda827x_cfg_0); + if (configure_tda827x_fe(dev, &avermedia_super_007_config, + &tda827x_cfg_0) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: - configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config, &tda827x_cfg_2_sw42); + if (configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config, + &tda827x_cfg_2_sw42) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_PHILIPS_SNAKE: dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, &dev->i2c_adap); if (dev->dvb.frontend) { if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, - &dev->i2c_adap, 0) == NULL) + &dev->i2c_adap, 0) == NULL) { wprintk("%s: No tda826x found!\n", __func__); + goto dettach_frontend; + } if (dvb_attach(lnbp21_attach, dev->dvb.frontend, - &dev->i2c_adap, 0, 0) == NULL) + &dev->i2c_adap, 0, 0) == NULL) { wprintk("%s: No lnbp21 found!\n", __func__); + goto dettach_frontend; + } } break; case SAA7134_BOARD_CREATIX_CTX953: - configure_tda827x_fe(dev, &md8800_dvbt_config, &tda827x_cfg_0); + if (configure_tda827x_fe(dev, &md8800_dvbt_config, + &tda827x_cfg_0) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_MSI_TVANYWHERE_AD11: - configure_tda827x_fe(dev, &philips_tiger_s_config, &tda827x_cfg_2); + if (configure_tda827x_fe(dev, &philips_tiger_s_config, + &tda827x_cfg_2) < 0) + goto dettach_frontend; break; case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: dev->dvb.frontend = dvb_attach(mt352_attach, @@ -1218,16 +1271,20 @@ static int dvb_init(struct saa7134_dev *dev) if (dev->dvb.frontend) { struct dvb_frontend *fe; if (dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, - &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) + &dev->i2c_adap, DVB_PLL_PHILIPS_SD1878_TDA8261) == NULL) { wprintk("%s: MD7134 DVB-S, no SD1878 " "found !\n", __func__); + goto dettach_frontend; + } /* we need to open the i2c gate (we know it exists) */ fe = dev->dvb.frontend; fe->ops.i2c_gate_ctrl(fe, 1); if (dvb_attach(isl6405_attach, fe, - &dev->i2c_adap, 0x08, 0, 0) == NULL) + &dev->i2c_adap, 0x08, 0, 0) == NULL) { wprintk("%s: MD7134 DVB-S, no ISL6405 " "found !\n", __func__); + goto dettach_frontend; + } fe->ops.i2c_gate_ctrl(fe, 0); dev->original_set_voltage = fe->ops.set_voltage; fe->ops.set_voltage = md8800_set_voltage; @@ -1254,10 +1311,7 @@ static int dvb_init(struct saa7134_dev *dev) if (!fe) { printk(KERN_ERR "%s/2: xc3028 attach failed\n", dev->name); - dvb_frontend_detach(dev->dvb.frontend); - dvb_unregister_frontend(dev->dvb.frontend); - dev->dvb.frontend = NULL; - return -1; + goto dettach_frontend; } } @@ -1282,6 +1336,13 @@ static int dvb_init(struct saa7134_dev *dev) dev->dvb.frontend->ops.tuner_ops.sleep(dev->dvb.frontend); } return ret; + +dettach_frontend: + dvb_frontend_detach(dev->dvb.frontend); + dvb_unregister_frontend(dev->dvb.frontend); + dev->dvb.frontend = NULL; + + return -1; } static int dvb_fini(struct saa7134_dev *dev) -- cgit v1.1 From 09fee5f8211fc0a586187c4a0db7f5f42a4e333f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Apr 2008 15:29:57 -0300 Subject: V4L/DVB (7802): tuner: Failures at tuner_attach were producing OOPS As reported by Mike Galbraith : [ 13.666587] TUNER: Unable to find symbol tda829x_probe() [ 13.674638] tuner' 1-004b: chip found @ 0x96 (saa7133[0]) [ 13.691175] DVB: Unable to find symbol tda9887_attach() [ 13.698968] BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 [ 13.709509] IP: [] strlcpy+0x11/0x36 [ 13.711135] PGD be167067 PUD be140067 PMD 0 [ 13.711137] Oops: 0000 [1] SMP Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tuner-core.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index c8cd718..b5dacde 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -340,16 +340,6 @@ static void tuner_i2c_address_check(struct tuner *t) tuner_warn("====================== WARNING! ======================\n"); } -static void attach_tda829x(struct tuner *t) -{ - struct tda829x_config cfg = { - .lna_cfg = t->config, - .tuner_callback = t->tuner_callback, - }; - dvb_attach(tda829x_attach, - &t->fe, t->i2c->adapter, t->i2c->addr, &cfg); -} - static struct xc5000_config xc5000_cfg; static void set_type(struct i2c_client *c, unsigned int type, @@ -385,12 +375,19 @@ static void set_type(struct i2c_client *c, unsigned int type, switch (t->type) { case TUNER_MT2032: - dvb_attach(microtune_attach, - &t->fe, t->i2c->adapter, t->i2c->addr); + if (!dvb_attach(microtune_attach, + &t->fe, t->i2c->adapter, t->i2c->addr)) + goto attach_failed; break; case TUNER_PHILIPS_TDA8290: { - attach_tda829x(t); + struct tda829x_config cfg = { + .lna_cfg = t->config, + .tuner_callback = t->tuner_callback, + }; + if (!dvb_attach(tda829x_attach, &t->fe, t->i2c->adapter, + t->i2c->addr, &cfg)) + goto attach_failed; break; } case TUNER_TEA5767: @@ -441,8 +438,9 @@ static void set_type(struct i2c_client *c, unsigned int type, break; } case TUNER_TDA9887: - dvb_attach(tda9887_attach, - &t->fe, t->i2c->adapter, t->i2c->addr); + if (!dvb_attach(tda9887_attach, + &t->fe, t->i2c->adapter, t->i2c->addr)) + goto attach_failed; break; case TUNER_XC5000: { -- cgit v1.1 From b538d28c2e326ed226096408dce4d9469d7ffa39 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Apr 2008 15:45:00 -0300 Subject: V4L/DVB (7804): tea5767: Fix error logic As pointed by Andrew Morton, the error testing were wrong. After reviewing tea5767, it were returning a positive value for errors. So, the double errors were cancelling each other. This patch fix it properly. It also considers any positive value as ok, on tuner-core. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tea5767.c | 6 +++--- drivers/media/video/tuner-core.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/common/tuners/tea5767.c b/drivers/media/common/tuners/tea5767.c index f6e7d7a..1f56463 100644 --- a/drivers/media/common/tuners/tea5767.c +++ b/drivers/media/common/tuners/tea5767.c @@ -373,14 +373,14 @@ int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr) if ((rc = tuner_i2c_xfer_recv(&i2c, buffer, 7))< 5) { printk(KERN_WARNING "It is not a TEA5767. Received %i bytes.\n", rc); - return EINVAL; + return -EINVAL; } /* If all bytes are the same then it's a TV tuner and not a tea5767 */ if (buffer[0] == buffer[1] && buffer[0] == buffer[2] && buffer[0] == buffer[3] && buffer[0] == buffer[4]) { printk(KERN_WARNING "All bytes are equal. It is not a TEA5767\n"); - return EINVAL; + return -EINVAL; } /* Status bytes: @@ -390,7 +390,7 @@ int tea5767_autodetection(struct i2c_adapter* i2c_adap, u8 i2c_addr) */ if (((buffer[3] & 0x0f) != 0x00) || (buffer[4] != 0x00)) { printk(KERN_WARNING "Chip ID is not zero. It is not a TEA5767\n"); - return EINVAL; + return -EINVAL; } diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index b5dacde..4ca686f 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -1165,7 +1165,7 @@ static int tuner_probe(struct i2c_client *client, /* If chip is not tda8290, don't register. since it can be tda9887*/ if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter, - t->i2c->addr) == 0) { + t->i2c->addr) >= 0) { tuner_dbg("tda829x detected\n"); } else { /* Default is being tda9887 */ @@ -1179,7 +1179,7 @@ static int tuner_probe(struct i2c_client *client, case 0x60: if (tuner_symbol_probe(tea5767_autodetection, t->i2c->adapter, t->i2c->addr) - != EINVAL) { + >= 0) { t->type = TUNER_TEA5767; t->mode_mask = T_RADIO; t->mode = T_STANDBY; -- cgit v1.1 From f50090fc947e82464b4a033c9eff1898cb0676b5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Apr 2008 18:13:05 -0300 Subject: V4L/DVB (7805): saa7134: dvb_unregister_frontend() shouldn't be called, if not registered yet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-dvb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 2a9aa72..469f93a 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1339,7 +1339,6 @@ static int dvb_init(struct saa7134_dev *dev) dettach_frontend: dvb_frontend_detach(dev->dvb.frontend); - dvb_unregister_frontend(dev->dvb.frontend); dev->dvb.frontend = NULL; return -1; -- cgit v1.1 From 6430a5a368208ae6c4bcd13e1f06460c96af66be Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Apr 2008 18:13:46 -0300 Subject: V4L/DVB (7806): em28xx: dvb_unregister_frontend() shouldn't be called, if not registered yet Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-dvb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/video/em28xx/em28xx-dvb.c b/drivers/media/video/em28xx/em28xx-dvb.c index 7df81575..8cf4983 100644 --- a/drivers/media/video/em28xx/em28xx-dvb.c +++ b/drivers/media/video/em28xx/em28xx-dvb.c @@ -251,7 +251,6 @@ static int attach_xc3028(u8 addr, struct em28xx *dev) printk(KERN_ERR "%s/2: xc3028 attach failed\n", dev->name); dvb_frontend_detach(dev->dvb->frontend); - dvb_unregister_frontend(dev->dvb->frontend); dev->dvb->frontend = NULL; return -EINVAL; } -- cgit v1.1 From 0590d91c413fb5144608d69f50710064360aeec8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Apr 2008 18:14:36 -0300 Subject: V4L/DVB (7807): cx88: Fix error handling, when dvb_attach() fails Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-dvb.c | 251 +++++++++++++++++++----------------- 1 file changed, 134 insertions(+), 117 deletions(-) diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 1c7fe68..75e2e58 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -509,9 +509,6 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) if (!fe) { printk(KERN_ERR "%s/2: xc3028 attach failed\n", dev->core->name); - dvb_frontend_detach(dev->dvb.frontend); - dvb_unregister_frontend(dev->dvb.frontend); - dev->dvb.frontend = NULL; return -EINVAL; } @@ -523,20 +520,23 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) static int dvb_register(struct cx8802_dev *dev) { + struct cx88_core *core = dev->core; + /* init struct videobuf_dvb */ - dev->dvb.name = dev->core->name; + dev->dvb.name = core->name; dev->ts_gen_cntrl = 0x0c; /* init frontend */ - switch (dev->core->boardnr) { + switch (core->boardnr) { case CX88_BOARD_HAUPPAUGE_DVB_T1: dev->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - &dev->core->i2c_adap, - DVB_PLL_THOMSON_DTT759X); + if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + 0x61, &core->i2c_adap, + DVB_PLL_THOMSON_DTT759X)) + goto frontend_detach; } break; case CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1: @@ -545,11 +545,12 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_WINFAST_DTV1000: dev->dvb.frontend = dvb_attach(cx22702_attach, &connexant_refboard_config, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, - &dev->core->i2c_adap, - DVB_PLL_THOMSON_DTT7579); + if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + 0x60, &core->i2c_adap, + DVB_PLL_THOMSON_DTT7579)) + goto frontend_detach; } break; case CX88_BOARD_WINFAST_DTV2000H: @@ -559,29 +560,32 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_HAUPPAUGE_HVR3000: dev->dvb.frontend = dvb_attach(cx22702_attach, &hauppauge_hvr_config, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(simple_tuner_attach, dev->dvb.frontend, - &dev->core->i2c_adap, 0x61, - TUNER_PHILIPS_FMD1216ME_MK3); + if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &core->i2c_adap, 0x61, + TUNER_PHILIPS_FMD1216ME_MK3)) + goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, - NULL, DVB_PLL_THOMSON_DTT7579); + if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) + goto frontend_detach; break; } /* ZL10353 replaces MT352 on later cards */ dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x60, - NULL, DVB_PLL_THOMSON_DTT7579); + if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + 0x60, NULL, DVB_PLL_THOMSON_DTT7579)) + goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_DUAL: @@ -589,28 +593,31 @@ static int dvb_register(struct cx8802_dev *dev) * compatible, with a slightly different MT352 AGC gain. */ dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_dual, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - NULL, DVB_PLL_THOMSON_DTT7579); + if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) + goto frontend_detach; break; } /* ZL10353 replaces MT352 on later cards */ dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_plus_v1_1, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - NULL, DVB_PLL_THOMSON_DTT7579); + if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + 0x61, NULL, DVB_PLL_THOMSON_DTT7579)) + goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - NULL, DVB_PLL_LG_Z201); + if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + 0x61, NULL, DVB_PLL_LG_Z201)) + goto frontend_detach; } break; case CX88_BOARD_KWORLD_DVB_T: @@ -618,10 +625,11 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_ADSTECH_DVB_T_PCI: dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_config, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(dvb_pll_attach, dev->dvb.frontend, 0x61, - NULL, DVB_PLL_UNKNOWN_1); + if (!dvb_attach(dvb_pll_attach, dev->dvb.frontend, + 0x61, NULL, DVB_PLL_UNKNOWN_1)) + goto frontend_detach; } break; case CX88_BOARD_DNTV_LIVE_DVB_T_PRO: @@ -630,32 +638,35 @@ static int dvb_register(struct cx8802_dev *dev) dev->dvb.frontend = dvb_attach(mt352_attach, &dntv_live_dvbt_pro_config, &dev->vp3054->adap); if (dev->dvb.frontend != NULL) { - dvb_attach(simple_tuner_attach, dev->dvb.frontend, - &dev->core->i2c_adap, 0x61, - TUNER_PHILIPS_FMD1216ME_MK3); + if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &core->i2c_adap, 0x61, + TUNER_PHILIPS_FMD1216ME_MK3)) + goto frontend_detach; } #else - printk(KERN_ERR "%s/2: built without vp3054 support\n", dev->core->name); + printk(KERN_ERR "%s/2: built without vp3054 support\n", + core->name); #endif break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_hybrid, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(simple_tuner_attach, dev->dvb.frontend, - &dev->core->i2c_adap, 0x61, - TUNER_THOMSON_FE6600); + if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &core->i2c_adap, 0x61, + TUNER_THOMSON_FE6600)) + goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: dev->dvb.frontend = dvb_attach(zl10353_attach, &dvico_fusionhdtv_xc3028, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend == NULL) dev->dvb.frontend = dvb_attach(mt352_attach, &dvico_fusionhdtv_mt352_xc3028, - &dev->core->i2c_adap); + &core->i2c_adap); /* * On this board, the demod provides the I2C bus pullup. * We must not permit gate_ctrl to be performed, or @@ -668,19 +679,18 @@ static int dvb_register(struct cx8802_dev *dev) break; case CX88_BOARD_PCHDTV_HD3000: dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(simple_tuner_attach, dev->dvb.frontend, - &dev->core->i2c_adap, 0x61, - TUNER_THOMSON_DTT761X); + if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &core->i2c_adap, 0x61, + TUNER_THOMSON_DTT761X)) + goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q: dev->ts_gen_cntrl = 0x08; - { - /* Do a hardware reset of chip before using it. */ - struct cx88_core *core = dev->core; + /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); @@ -690,139 +700,138 @@ static int dvb_register(struct cx8802_dev *dev) fusionhdtv_3_gold.pll_rf_set = lgdt330x_pll_rf_set; dev->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(simple_tuner_attach, dev->dvb.frontend, - &dev->core->i2c_adap, 0x61, - TUNER_MICROTUNE_4042FI5); - } + if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &core->i2c_adap, 0x61, + TUNER_MICROTUNE_4042FI5)) + goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T: dev->ts_gen_cntrl = 0x08; - { - /* Do a hardware reset of chip before using it. */ - struct cx88_core *core = dev->core; + /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 9); mdelay(200); dev->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_3_gold, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(simple_tuner_attach, dev->dvb.frontend, - &dev->core->i2c_adap, 0x61, - TUNER_THOMSON_DTT761X); - } + if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &core->i2c_adap, 0x61, + TUNER_THOMSON_DTT761X)) + goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: dev->ts_gen_cntrl = 0x08; - { - /* Do a hardware reset of chip before using it. */ - struct cx88_core *core = dev->core; + /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); dev->dvb.frontend = dvb_attach(lgdt330x_attach, &fusionhdtv_5_gold, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(simple_tuner_attach, dev->dvb.frontend, - &dev->core->i2c_adap, 0x61, - TUNER_LG_TDVS_H06XF); - dvb_attach(tda9887_attach, dev->dvb.frontend, - &dev->core->i2c_adap, 0x43); - } + if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &core->i2c_adap, 0x61, + TUNER_LG_TDVS_H06XF)) + goto frontend_detach; + if (!dvb_attach(tda9887_attach, dev->dvb.frontend, + &core->i2c_adap, 0x43)) + goto frontend_detach; } break; case CX88_BOARD_PCHDTV_HD5500: dev->ts_gen_cntrl = 0x08; - { - /* Do a hardware reset of chip before using it. */ - struct cx88_core *core = dev->core; + /* Do a hardware reset of chip before using it. */ cx_clear(MO_GP0_IO, 1); mdelay(100); cx_set(MO_GP0_IO, 1); mdelay(200); dev->dvb.frontend = dvb_attach(lgdt330x_attach, &pchdtv_hd5500, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(simple_tuner_attach, dev->dvb.frontend, - &dev->core->i2c_adap, 0x61, - TUNER_LG_TDVS_H06XF); - dvb_attach(tda9887_attach, dev->dvb.frontend, - &dev->core->i2c_adap, 0x43); - } + if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &core->i2c_adap, 0x61, + TUNER_LG_TDVS_H06XF)) + goto frontend_detach; + if (!dvb_attach(tda9887_attach, dev->dvb.frontend, + &core->i2c_adap, 0x43)) + goto frontend_detach; } break; case CX88_BOARD_ATI_HDTVWONDER: dev->dvb.frontend = dvb_attach(nxt200x_attach, &ati_hdtvwonder, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { - dvb_attach(simple_tuner_attach, dev->dvb.frontend, - &dev->core->i2c_adap, 0x61, - TUNER_PHILIPS_TUV1236D); + if (!dvb_attach(simple_tuner_attach, dev->dvb.frontend, + &core->i2c_adap, 0x61, + TUNER_PHILIPS_TUV1236D)) + goto frontend_detach; } break; case CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1: case CX88_BOARD_HAUPPAUGE_NOVASE2_S1: dev->dvb.frontend = dvb_attach(cx24123_attach, &hauppauge_novas_config, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend) { - dvb_attach(isl6421_attach, dev->dvb.frontend, - &dev->core->i2c_adap, 0x08, 0x00, 0x00); + if (!dvb_attach(isl6421_attach, dev->dvb.frontend, + &core->i2c_adap, 0x08, 0x00, 0x00)) + goto frontend_detach; } break; case CX88_BOARD_KWORLD_DVBS_100: dev->dvb.frontend = dvb_attach(cx24123_attach, &kworld_dvbs_100_config, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend) { - dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; + core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; dev->dvb.frontend->ops.set_voltage = kworld_dvbs_100_set_voltage; } break; case CX88_BOARD_GENIATECH_DVBS: dev->dvb.frontend = dvb_attach(cx24123_attach, &geniatech_dvbs_config, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend) { - dev->core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; + core->prev_set_voltage = dev->dvb.frontend->ops.set_voltage; dev->dvb.frontend->ops.set_voltage = geniatech_dvbs_set_voltage; } break; case CX88_BOARD_PINNACLE_PCTV_HD_800i: dev->dvb.frontend = dvb_attach(s5h1409_attach, &pinnacle_pctv_hd_800i_config, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { /* tuner_config.video_dev must point to * i2c_adap.algo_data */ pinnacle_pctv_hd_800i_tuner_config.priv = - dev->core->i2c_adap.algo_data; - dvb_attach(xc5000_attach, dev->dvb.frontend, - &dev->core->i2c_adap, - &pinnacle_pctv_hd_800i_tuner_config); + core->i2c_adap.algo_data; + if (!dvb_attach(xc5000_attach, dev->dvb.frontend, + &core->i2c_adap, + &pinnacle_pctv_hd_800i_tuner_config)) + goto frontend_detach; } break; case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: dev->dvb.frontend = dvb_attach(s5h1409_attach, &dvico_hdtv5_pci_nano_config, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { struct dvb_frontend *fe; struct xc2028_config cfg = { - .i2c_adap = &dev->core->i2c_adap, + .i2c_adap = &core->i2c_adap, .i2c_addr = 0x61, .callback = cx88_pci_nano_callback, }; @@ -841,50 +850,51 @@ static int dvb_register(struct cx8802_dev *dev) case CX88_BOARD_PINNACLE_HYBRID_PCTV: dev->dvb.frontend = dvb_attach(zl10353_attach, &cx88_geniatech_x8000_mt, - &dev->core->i2c_adap); + &core->i2c_adap); if (attach_xc3028(0x61, dev) < 0) - return -EINVAL; + goto frontend_detach; break; case CX88_BOARD_GENIATECH_X8000_MT: dev->ts_gen_cntrl = 0x00; dev->dvb.frontend = dvb_attach(zl10353_attach, &cx88_geniatech_x8000_mt, - &dev->core->i2c_adap); + &core->i2c_adap); if (attach_xc3028(0x61, dev) < 0) - return -EINVAL; + goto frontend_detach; break; case CX88_BOARD_KWORLD_ATSC_120: dev->dvb.frontend = dvb_attach(s5h1409_attach, &kworld_atsc_120_config, - &dev->core->i2c_adap); + &core->i2c_adap); if (attach_xc3028(0x61, dev) < 0) - return -EINVAL; + goto frontend_detach; break; case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: dev->dvb.frontend = dvb_attach(s5h1411_attach, &dvico_fusionhdtv7_config, - &dev->core->i2c_adap); + &core->i2c_adap); if (dev->dvb.frontend != NULL) { /* tuner_config.video_dev must point to * i2c_adap.algo_data */ dvico_fusionhdtv7_tuner_config.priv = - dev->core->i2c_adap.algo_data; - dvb_attach(xc5000_attach, dev->dvb.frontend, - &dev->core->i2c_adap, - &dvico_fusionhdtv7_tuner_config); + core->i2c_adap.algo_data; + if (!dvb_attach(xc5000_attach, dev->dvb.frontend, + &core->i2c_adap, + &dvico_fusionhdtv7_tuner_config)) + goto frontend_detach; } break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", - dev->core->name); + core->name); break; } if (NULL == dev->dvb.frontend) { printk(KERN_ERR "%s/2: frontend initialization failed\n", - dev->core->name); + core->name); return -EINVAL; } @@ -892,11 +902,18 @@ static int dvb_register(struct cx8802_dev *dev) dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; /* Put the analog decoder in standby to keep it quiet */ - cx88_call_i2c_clients (dev->core, TUNER_SET_STANDBY, NULL); + cx88_call_i2c_clients(core, TUNER_SET_STANDBY, NULL); /* register everything */ return videobuf_dvb_register(&dev->dvb, THIS_MODULE, dev, &dev->pci->dev, adapter_nr); + +frontend_detach: + if (dev->dvb.frontend) { + dvb_frontend_detach(dev->dvb.frontend); + dev->dvb.frontend = NULL; + } + return -EINVAL; } /* ----------------------------------------------------------- */ -- cgit v1.1 From b4edcc9083af9444b288ee9e14cab28b29dc3636 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 30 Apr 2008 12:36:09 -0300 Subject: V4L/DVB (7808): cx23885: fix kbuild dependencies Thanks to Ingo Molnar for finding this. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index cadf936..c50d451 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -9,6 +9,8 @@ config VIDEO_CX23885 select VIDEO_IR select VIDEOBUF_DVB select VIDEO_CX25840 + select VIDEO_CX2341X + select DVB_DIB7000P if !DVB_FE_CUSTOMISE select MEDIA_TUNER_MT2131 if !DVB_FE_CUSTOMISE select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE -- cgit v1.1 From b7eccc404f399ab93ed128e51ca5d6e0e5115dd2 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Wed, 30 Apr 2008 09:21:33 -0300 Subject: V4L/DVB (7810): soc_camera: mt9v022 and mt9m001 depend on I2C Both mt9v022 and mt9m001 cameras are controlled over the I2C bus. Respectively, their drivers require I2C to be built successfully. Thanks to Ingo Molnar for reporting the build-breakage. Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index fe743aa..98e2e1a2 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -906,7 +906,7 @@ config SOC_CAMERA config SOC_CAMERA_MT9M001 tristate "mt9m001 support" - depends on SOC_CAMERA + depends on SOC_CAMERA && I2C select GPIO_PCA953X if MT9M001_PCA9536_SWITCH help This driver supports MT9M001 cameras from Micron, monochrome @@ -921,7 +921,7 @@ config MT9M001_PCA9536_SWITCH config SOC_CAMERA_MT9V022 tristate "mt9v022 support" - depends on SOC_CAMERA + depends on SOC_CAMERA && I2C select GPIO_PCA953X if MT9V022_PCA9536_SWITCH help This driver supports MT9V022 cameras from Micron -- cgit v1.1 From ef69c8e88bafdeb896395fa5379a4b8c6a10bb08 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 1 May 2008 02:17:24 -0300 Subject: V4L/DVB (7813): Fix compilation, when V4L1_COMPAT is disabled This driver uses some sysfs helper functions that are available only for legacy drivers. It also requires linux/mm.h. This patch fixes compiliation when not in compat mode. Thanks to Ingo Molnar for identifying this issue. Acked-by: Jaime Velasco Juan Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/stk-webcam.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/media/video/stk-webcam.c b/drivers/media/video/stk-webcam.c index 9276ed9..b12c60c 100644 --- a/drivers/media/video/stk-webcam.c +++ b/drivers/media/video/stk-webcam.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include @@ -245,6 +246,8 @@ static int stk_initialise(struct stk_camera *dev) return -1; } +#ifdef CONFIG_VIDEO_V4L1_COMPAT + /* sysfs functions */ /*FIXME cleanup this */ @@ -350,6 +353,10 @@ static void stk_remove_sysfs_files(struct video_device *vdev) video_device_remove_file(vdev, &dev_attr_vflip); } +#else +#define stk_create_sysfs_files(a) +#define stk_remove_sysfs_files(a) +#endif /* *********************************************** */ /* -- cgit v1.1 From 74ee05109c9d6ae2dfe1b462592d3854ddbf1f6a Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Thu, 1 May 2008 18:02:30 -0300 Subject: V4L/DVB (7823): em28xx: add additional usb subids for Hauppauge HVR-950 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.em28xx | 2 +- drivers/media/video/em28xx/em28xx-cards.c | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Documentation/video4linux/CARDLIST.em28xx b/Documentation/video4linux/CARDLIST.em28xx index f40e092..1d6a245 100644 --- a/Documentation/video4linux/CARDLIST.em28xx +++ b/Documentation/video4linux/CARDLIST.em28xx @@ -14,4 +14,4 @@ 13 -> Terratec Prodigy XS (em2880) [0ccd:0047] 14 -> Pixelview Prolink PlayTV USB 2.0 (em2820/em2840) 15 -> V-Gear PocketTV (em2800) - 16 -> Hauppauge WinTV HVR 950 (em2880) [2040:6513] + 16 -> Hauppauge WinTV HVR 950 (em2880) [2040:6513,2040:6517,2040:651b,2040:651f] diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 50ccf37..3e4f3c7 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -420,7 +420,13 @@ struct usb_device_id em28xx_id_table [] = { .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, { USB_DEVICE(0x2040, 0x6502), .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_900 }, - { USB_DEVICE(0x2040, 0x6513), + { USB_DEVICE(0x2040, 0x6513), /* HCW HVR-980 */ + .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 }, + { USB_DEVICE(0x2040, 0x6517), /* HP HVR-950 */ + .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 }, + { USB_DEVICE(0x2040, 0x651b), /* RP HVR-950 */ + .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 }, + { USB_DEVICE(0x2040, 0x651f), /* HCW HVR-850 */ .driver_info = EM2880_BOARD_HAUPPAUGE_WINTV_HVR_950 }, { USB_DEVICE(0x0ccd, 0x0042), .driver_info = EM2880_BOARD_TERRATEC_HYBRID_XS }, -- cgit v1.1 From 3c3852cda6e0c557f5e0915b5451510c1acd64a2 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 2 May 2008 16:12:44 -0300 Subject: V4L/DVB (7827): cx23885: add missing subsystem ID for Hauppauge HVR-1200 OEM Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 2 +- drivers/media/video/cx23885/cx23885-cards.c | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index 929b90c..191194e 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -5,6 +5,6 @@ 4 -> DViCO FusionHDTV5 Express [18ac:d500] 5 -> Hauppauge WinTV-HVR1500Q [0070:7790,0070:7797] 6 -> Hauppauge WinTV-HVR1500 [0070:7710,0070:7717] - 7 -> Hauppauge WinTV-HVR1200 [0070:71d1] + 7 -> Hauppauge WinTV-HVR1200 [0070:71d1,0070:71d3] 8 -> Hauppauge WinTV-HVR1700 [0070:8101] 9 -> Hauppauge WinTV-HVR1400 [0070:8010] diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 6ebf587..8c38011 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -200,6 +200,10 @@ struct cx23885_subid cx23885_subids[] = { .card = CX23885_BOARD_HAUPPAUGE_HVR1200, }, { .subvendor = 0x0070, + .subdevice = 0x71d3, + .card = CX23885_BOARD_HAUPPAUGE_HVR1200, + }, { + .subvendor = 0x0070, .subdevice = 0x8101, .card = CX23885_BOARD_HAUPPAUGE_HVR1700, }, { -- cgit v1.1 From 36396c893272a577eafad40630a609ccd36d20ea Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 2 May 2008 16:14:33 -0300 Subject: V4L/DVB (7828): cx23885: update model matrix for Hauppauge WinTV HVR-1200 & WinTV HVR-1700 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/cx23885-cards.c | 32 ++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 8c38011..20e05f2 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -249,6 +249,33 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) /* Make sure we support the board model */ switch (tv.model) { + case 71009: + /* WinTV-HVR1200 (PCIe, Retail, full height) + * DVB-T and basic analog */ + case 71359: + /* WinTV-HVR1200 (PCIe, OEM, half height) + * DVB-T and basic analog */ + case 71439: + /* WinTV-HVR1200 (PCIe, OEM, half height) + * DVB-T and basic analog */ + case 71449: + /* WinTV-HVR1200 (PCIe, OEM, full height) + * DVB-T and basic analog */ + case 71939: + /* WinTV-HVR1200 (PCIe, OEM, half height) + * DVB-T and basic analog */ + case 71949: + /* WinTV-HVR1200 (PCIe, OEM, full height) + * DVB-T and basic analog */ + case 71959: + /* WinTV-HVR1200 (PCIe, OEM, full height) + * DVB-T and basic analog */ + case 71979: + /* WinTV-HVR1200 (PCIe, OEM, half height) + * DVB-T and basic analog */ + case 71999: + /* WinTV-HVR1200 (PCIe, OEM, full height) + * DVB-T and basic analog */ case 76601: /* WinTV-HVR1800lp (PCIe, Retail, No IR, Dual channel ATSC and MPEG2 HW Encoder */ case 77001: /* WinTV-HVR1500 (Express Card, OEM, No IR, ATSC and Basic analog */ case 77011: /* WinTV-HVR1500 (Express Card, Retail, No IR, ATSC and Basic analog */ @@ -267,8 +294,11 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) case 80019: /* WinTV-HVR1400 (Express Card, Retail, IR, * DVB-T and Basic analog */ + case 81509: + /* WinTV-HVR1700 (PCIe, OEM, No IR, half height) + * DVB-T and MPEG2 HW Encoder */ case 81519: - /* WinTV-HVR1700 (PCIe, Retail, No IR, half height, + /* WinTV-HVR1700 (PCIe, OEM, No IR, full height) * DVB-T and MPEG2 HW Encoder */ break; default: -- cgit v1.1 From fa146c6dceffa68fa12f8d0b797ab9753fa1c792 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Fri, 2 May 2008 16:20:10 -0300 Subject: V4L/DVB (7829): cx23885: remove remaining references to dvb-pll The cx23885 driver used to use dvb-pll for LG-TDVS-H064F support on the FusionHDTV5 Express. This has since been converted to use tuner-simple instead, once digital tuning support was added to tuner-simple. Since cx23885 no longer uses dvb-pll, remove the #include "dvb-pll.h", and the DVB_PLL Kconfig selection. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx23885/Kconfig | 1 - drivers/media/video/cx23885/cx23885-dvb.c | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index c50d451..013e18c 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -14,7 +14,6 @@ config VIDEO_CX23885 select MEDIA_TUNER_MT2131 if !DVB_FE_CUSTOMISE select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE - select DVB_PLL if !DVB_FE_CUSTOMISE select MEDIA_TUNER_XC2028 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_TDA18271 if !DVB_FE_CUSTOMIZE diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index f056497..47e3f9e 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -37,7 +37,6 @@ #include "lgdt330x.h" #include "xc5000.h" #include "tda10048.h" -#include "dvb-pll.h" #include "tuner-xc2028.h" #include "tuner-simple.h" #include "dib7000p.h" -- cgit v1.1 From 71a35fe2a345eb3704e1f1b4da65451d3e2b8c2e Mon Sep 17 00:00:00 2001 From: Robert Schedel Date: Sat, 3 May 2008 12:58:36 -0300 Subject: V4L/DVB (7830): dvb_ca_en50221: Fix High CPU load in 'top' due to budget_av slot polling This change addresses kernel bug #10459: In kernel 2.6.25 the budget_av driver polls for an CI slot in 100ms intervals (because no interrupt solution for budget_av cards is feasible due to HW reasons). If no CI/CAM is connected to the DVB card, polling times out only after 250ms. This periodic polling leads to high CPU load. The change increases the polling interval for empty slots from 100ms to 5s. Intervals for remaining slot states (invalid, in progress, ready) are unchanged, as they are either temporary conditions or no timeout should occur. Signed-off-by: Robert Schedel Signed-off-by: Oliver Endriss Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_ca_en50221.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c index 8cbdb0e..588fbe1 100644 --- a/drivers/media/dvb/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb/dvb-core/dvb_ca_en50221.c @@ -910,15 +910,21 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca) int curdelay = 100000000; int slot; + /* Beware of too high polling frequency, because one polling + * call might take several hundred milliseconds until timeout! + */ for (slot = 0; slot < ca->slot_count; slot++) { switch (ca->slot_info[slot].slot_state) { default: case DVB_CA_SLOTSTATE_NONE: + delay = HZ * 60; /* 60s */ + if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) + delay = HZ * 5; /* 5s */ + break; case DVB_CA_SLOTSTATE_INVALID: - delay = HZ * 60; - if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) { - delay = HZ / 10; - } + delay = HZ * 60; /* 60s */ + if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) + delay = HZ / 10; /* 100ms */ break; case DVB_CA_SLOTSTATE_UNINITIALISED: @@ -926,19 +932,17 @@ static void dvb_ca_en50221_thread_update_delay(struct dvb_ca_private *ca) case DVB_CA_SLOTSTATE_VALIDATE: case DVB_CA_SLOTSTATE_WAITFR: case DVB_CA_SLOTSTATE_LINKINIT: - delay = HZ / 10; + delay = HZ / 10; /* 100ms */ break; case DVB_CA_SLOTSTATE_RUNNING: - delay = HZ * 60; - if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) { - delay = HZ / 10; - } + delay = HZ * 60; /* 60s */ + if (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE)) + delay = HZ / 10; /* 100ms */ if (ca->open) { if ((!ca->slot_info[slot].da_irq_supported) || - (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA))) { - delay = HZ / 10; - } + (!(ca->flags & DVB_CA_EN50221_FLAG_IRQ_DA))) + delay = HZ / 10; /* 100ms */ } break; } -- cgit v1.1 From f686d8c3b53c7b105330b5292ff5d44bb04e4971 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Mon, 5 May 2008 21:08:28 -0300 Subject: V4L/DVB (7832): xc5000: MEDIA_TUNER_XC5000 must select FW_LOADER Fix the following build error: drivers/built-in.o: In function `xc_load_fw_and_init_tuner': xc5000.c:(.text+0x2dacd): undefined reference to `request_firmware' xc5000.c:(.text+0x2daf0): undefined reference to `release_firmware' xc5000.c:(.text+0x2db85): undefined reference to `release_firmware' make[1]: *** [.tmp_vmlinux1] Error 1 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index 5be85ff..c0b472e 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig @@ -142,6 +142,7 @@ config MEDIA_TUNER_XC2028 config MEDIA_TUNER_XC5000 tristate "Xceive XC5000 silicon tuner" depends on I2C + select FW_LOADER default m if DVB_FE_CUSTOMISE help A driver for the silicon tuner XC5000 from Xceive. -- cgit v1.1 From 28dd15b4334c2ded53d7738160861aa16304b8fd Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sat, 3 May 2008 21:23:51 -0300 Subject: V4L/DVB (7834): build fix for drivers/media/video/au0828 x86.git testing found the following build failure in v2.6.26-rc1: MODPOST 424 modules ERROR: "tveeprom_hauppauge_analog" [drivers/media/video/au0828/au0828.ko] undefined! ERROR: "tveeprom_read" [drivers/media/video/au0828/au0828.ko] undefined! with this config: http://redhat.com/~mingo/misc/config-Sat_May__3_22_28_58_CEST_2008.bad this patch does what other video drivers do to utilize the VIDEO_TVEEPROM functionality (and this resolves the build problem) - but i have not checked it on real hardware and i have not checked whether the fix is complete. selections, so some items might still be missing - just not triggered with this specific config. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig index cab277f..4d99b1a 100644 --- a/drivers/media/video/au0828/Kconfig +++ b/drivers/media/video/au0828/Kconfig @@ -3,6 +3,7 @@ config VIDEO_AU0828 tristate "Auvitek AU0828 support" depends on VIDEO_DEV && I2C && INPUT && DVB_CORE select I2C_ALGOBIT + select VIDEO_TVEEPROM select DVB_AU8522 if !DVB_FE_CUSTOMIZE select MEDIA_TUNER_XC5000 if !DVB_FE_CUSTOMIZE ---help--- -- cgit v1.1 From 696b9562df15795facf9ffbd470983e776fa6c19 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 5 May 2008 19:20:42 -0300 Subject: V4L/DVB (7835): multimedia/video: fix au0828 Kconfig Fix undefined references in au0828: depends on USB and select VIDEO_TVEEPROM Signed-off-by: Randy Dunlap Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/au0828/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/au0828/Kconfig b/drivers/media/video/au0828/Kconfig index 4d99b1a..def10d0 100644 --- a/drivers/media/video/au0828/Kconfig +++ b/drivers/media/video/au0828/Kconfig @@ -1,7 +1,7 @@ config VIDEO_AU0828 tristate "Auvitek AU0828 support" - depends on VIDEO_DEV && I2C && INPUT && DVB_CORE + depends on VIDEO_DEV && I2C && INPUT && DVB_CORE && USB select I2C_ALGOBIT select VIDEO_TVEEPROM select DVB_AU8522 if !DVB_FE_CUSTOMIZE -- cgit v1.1 From dc9d522a1358bfb87e9ed8718cc1e4d5141a5468 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Sun, 4 May 2008 20:32:45 -0300 Subject: V4L/DVB (7836): cinergyT2 build fix x86.git testing found the following build bug in v2.6.26-rc1: drivers/built-in.o: In function `cinergyt2_probe': cinergyT2.c:(.text+0xb6117): undefined reference to `input_allocate_device' cinergyT2.c:(.text+0xb6230): undefined reference to `input_register_device' cinergyT2.c:(.text+0xb623d): undefined reference to `input_free_device' with the following config: http://redhat.com/~mingo/misc/config-Sun_May__4_22_06_54_CEST_2008.bad The reason for the bug is that the cinergyT2 driver depends on CONFIG_INPUT functionality, but if INPUT is modular it's still possible to build CONFIG_DVB_CINERGYT2=y - which leads to missing symbols. The solution is to make DVB_CINERGYT2 dependent on INPUT. [ This solves the build problem - i have not tested the driver on this card. ] Signed-off-by: Ingo Molnar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/cinergyT2/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/cinergyT2/Kconfig b/drivers/media/dvb/cinergyT2/Kconfig index 3d778c5..c03513b 100644 --- a/drivers/media/dvb/cinergyT2/Kconfig +++ b/drivers/media/dvb/cinergyT2/Kconfig @@ -1,6 +1,6 @@ config DVB_CINERGYT2 tristate "Terratec CinergyT2/qanu USB2 DVB-T receiver" - depends on DVB_CORE && USB + depends on DVB_CORE && USB && INPUT help Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers -- cgit v1.1 From d35fccaffd095e79691cd07a49a36867cb275b72 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 3 May 2008 18:20:21 -0300 Subject: V4L/DVB (7837): tda18271: fix error handling in init and sleep paths Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-common.c | 7 ++--- drivers/media/common/tuners/tda18271-fe.c | 38 ++++++++++++++++++--------- 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c index e27a762..9001d42 100644 --- a/drivers/media/common/tuners/tda18271-common.c +++ b/drivers/media/common/tuners/tda18271-common.c @@ -227,9 +227,8 @@ int tda18271_charge_pump_source(struct dvb_frontend *fe, regs[r_cp] &= ~0x20; regs[r_cp] |= ((force & 1) << 5); - tda18271_write_regs(fe, r_cp, 1); - return 0; + return tda18271_write_regs(fe, r_cp, 1); } int tda18271_init_regs(struct dvb_frontend *fe) @@ -494,9 +493,7 @@ int tda18271_set_standby_mode(struct dvb_frontend *fe, sm_lt ? (1 << 6) : 0 | sm_xt ? (1 << 5) : 0; - tda18271_write_regs(fe, R_EP3, 1); - - return 0; + return tda18271_write_regs(fe, R_EP3, 1); } /*---------------------------------------------------------------------*/ diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index b262100..46c0800 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -719,45 +719,56 @@ static int tda18271_ir_cal_init(struct dvb_frontend *fe) { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; + int ret; - tda18271_read_regs(fe); + ret = tda18271_read_regs(fe); + if (ret < 0) + goto fail; /* test IR_CAL_OK to see if we need init */ if ((regs[R_EP1] & 0x08) == 0) - tda18271_init_regs(fe); - - return 0; + ret = tda18271_init_regs(fe); +fail: + return ret; } static int tda18271_init(struct dvb_frontend *fe) { struct tda18271_priv *priv = fe->tuner_priv; + int ret; mutex_lock(&priv->lock); /* power up */ - tda18271_set_standby_mode(fe, 0, 0, 0); + ret = tda18271_set_standby_mode(fe, 0, 0, 0); + if (ret < 0) + goto fail; /* initialization */ - tda18271_ir_cal_init(fe); + ret = tda18271_ir_cal_init(fe); + if (ret < 0) + goto fail; if (priv->id == TDA18271HDC2) tda18271c2_rf_cal_init(fe); - +fail: mutex_unlock(&priv->lock); - return 0; + return ret; } static int tda18271_tune(struct dvb_frontend *fe, struct tda18271_std_map_item *map, u32 freq, u32 bw) { struct tda18271_priv *priv = fe->tuner_priv; + int ret; tda_dbg("freq = %d, ifc = %d, bw = %d, agc_mode = %d, std = %d\n", freq, map->if_freq, bw, map->agc_mode, map->std); - tda18271_init(fe); + ret = tda18271_init(fe); + if (ret < 0) + goto fail; mutex_lock(&priv->lock); @@ -772,8 +783,8 @@ static int tda18271_tune(struct dvb_frontend *fe, tda18271_channel_configuration(fe, map, freq, bw); mutex_unlock(&priv->lock); - - return 0; +fail: + return ret; } /* ------------------------------------------------------------------ */ @@ -905,16 +916,17 @@ fail: static int tda18271_sleep(struct dvb_frontend *fe) { struct tda18271_priv *priv = fe->tuner_priv; + int ret; mutex_lock(&priv->lock); /* standby mode w/ slave tuner output * & loop thru & xtal oscillator on */ - tda18271_set_standby_mode(fe, 1, 0, 0); + ret = tda18271_set_standby_mode(fe, 1, 0, 0); mutex_unlock(&priv->lock); - return 0; + return ret; } static int tda18271_release(struct dvb_frontend *fe) -- cgit v1.1 From 24124f784bfec447f5cb9e64ed337afb57f0fca5 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 3 May 2008 19:28:00 -0300 Subject: V4L/DVB (7838): tda18271: fix error handling in tda18271c2_rf_cal_init path fix error handling in tda18271c2_rf_cal_init immediate path Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 68 +++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 21 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 46c0800..d4fdcd4 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -259,26 +259,33 @@ static int tda18271_por(struct dvb_frontend *fe) { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; + int ret; /* power up detector 1 */ regs[R_EB12] &= ~0x20; - tda18271_write_regs(fe, R_EB12, 1); + ret = tda18271_write_regs(fe, R_EB12, 1); + if (ret < 0) + goto fail; regs[R_EB18] &= ~0x80; /* turn agc1 loop on */ regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */ - tda18271_write_regs(fe, R_EB18, 1); + ret = tda18271_write_regs(fe, R_EB18, 1); + if (ret < 0) + goto fail; regs[R_EB21] |= 0x03; /* set agc2_gain to -6 dB */ /* POR mode */ - tda18271_set_standby_mode(fe, 1, 0, 0); + ret = tda18271_set_standby_mode(fe, 1, 0, 0); + if (ret < 0) + goto fail; /* disable 1.5 MHz low pass filter */ regs[R_EB23] &= ~0x04; /* forcelp_fc2_en = 0 */ regs[R_EB23] &= ~0x02; /* XXX: lp_fc[2] = 0 */ - tda18271_write_regs(fe, R_EB21, 3); - - return 0; + ret = tda18271_write_regs(fe, R_EB21, 3); +fail: + return ret; } static int tda18271_calibrate_rf(struct dvb_frontend *fe, u32 freq) @@ -389,7 +396,7 @@ static int tda18271_powerscan(struct dvb_frontend *fe, { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; - int sgn, bcal, count, wait; + int sgn, bcal, count, wait, ret; u8 cid_target; u16 count_limit; u32 freq; @@ -421,7 +428,9 @@ static int tda18271_powerscan(struct dvb_frontend *fe, tda18271_write_regs(fe, R_EP2, 1); /* read power detection info, stored in EB10 */ - tda18271_read_extended(fe); + ret = tda18271_read_extended(fe); + if (ret < 0) + return ret; /* algorithm initialization */ sgn = 1; @@ -447,7 +456,9 @@ static int tda18271_powerscan(struct dvb_frontend *fe, tda18271_write_regs(fe, R_EP2, 1); /* read power detection info, stored in EB10 */ - tda18271_read_extended(fe); + ret = tda18271_read_extended(fe); + if (ret < 0) + return ret; count += 200; @@ -478,6 +489,7 @@ static int tda18271_powerscan_init(struct dvb_frontend *fe) { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; + int ret; /* set standard to digital */ regs[R_EP3] &= ~0x1f; /* clear std bits */ @@ -489,10 +501,14 @@ static int tda18271_powerscan_init(struct dvb_frontend *fe) /* update IF output level & IF notch frequency */ regs[R_EP4] &= ~0x1c; /* clear if level bits */ - tda18271_write_regs(fe, R_EP3, 2); + ret = tda18271_write_regs(fe, R_EP3, 2); + if (ret < 0) + goto fail; regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */ - tda18271_write_regs(fe, R_EB18, 1); + ret = tda18271_write_regs(fe, R_EB18, 1); + if (ret < 0) + goto fail; regs[R_EB21] &= ~0x03; /* set agc2_gain to -15 dB */ @@ -500,9 +516,9 @@ static int tda18271_powerscan_init(struct dvb_frontend *fe) regs[R_EB23] |= 0x04; /* forcelp_fc2_en = 1 */ regs[R_EB23] |= 0x02; /* lp_fc[2] = 1 */ - tda18271_write_regs(fe, R_EB21, 3); - - return 0; + ret = tda18271_write_regs(fe, R_EB21, 3); +fail: + return ret; } static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq) @@ -535,6 +551,8 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq) /* look for optimized calibration frequency */ bcal = tda18271_powerscan(fe, &rf_default[rf], &rf_freq[rf]); + if (bcal < 0) + return bcal; tda18271_calc_rf_cal(fe, &rf_freq[rf]); prog_tab[rf] = regs[R_EB14]; @@ -575,13 +593,16 @@ static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe) { struct tda18271_priv *priv = fe->tuner_priv; unsigned int i; + int ret; tda_info("tda18271: performing RF tracking filter calibration\n"); /* wait for die temperature stabilization */ msleep(200); - tda18271_powerscan_init(fe); + ret = tda18271_powerscan_init(fe); + if (ret < 0) + goto fail; /* rf band calibration */ for (i = 0; priv->rf_cal_state[i].rfmax != 0; i++) @@ -589,8 +610,8 @@ static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe) priv->rf_cal_state[i].rfmax); priv->tm_rfcal = tda18271_read_thermometer(fe); - - return 0; +fail: + return ret; } /* ------------------------------------------------------------------ */ @@ -599,6 +620,7 @@ static int tda18271c2_rf_cal_init(struct dvb_frontend *fe) { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; + int ret; /* test RF_CAL_OK to see if we need init */ if ((regs[R_EP1] & 0x10) == 0) @@ -607,15 +629,19 @@ static int tda18271c2_rf_cal_init(struct dvb_frontend *fe) if (priv->cal_initialized) return 0; - tda18271_calc_rf_filter_curve(fe); + ret = tda18271_calc_rf_filter_curve(fe); + if (ret < 0) + goto fail; - tda18271_por(fe); + ret = tda18271_por(fe); + if (ret < 0) + goto fail; tda_info("tda18271: RF tracking filter calibration complete\n"); priv->cal_initialized = true; - - return 0; +fail: + return ret; } static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe, -- cgit v1.1 From c151c32fd7d8f5ca7dcd35430f2e625181c48d66 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 4 May 2008 17:54:23 -0300 Subject: V4L/DVB (7839): tda18271: abort rf band calibration loop on errors Abort rf band calibration loop for the TDA18271HD/C2 if an error is detected. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index d4fdcd4..3f7ca45 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -605,9 +605,13 @@ static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe) goto fail; /* rf band calibration */ - for (i = 0; priv->rf_cal_state[i].rfmax != 0; i++) + for (i = 0; priv->rf_cal_state[i].rfmax != 0; i++) { + ret = tda18271_rf_tracking_filters_init(fe, 1000 * priv->rf_cal_state[i].rfmax); + if (ret < 0) + goto fail; + } priv->tm_rfcal = tda18271_read_thermometer(fe); fail: @@ -640,7 +644,10 @@ static int tda18271c2_rf_cal_init(struct dvb_frontend *fe) tda_info("tda18271: RF tracking filter calibration complete\n"); priv->cal_initialized = true; + goto end; fail: + tda_info("tda18271: RF tracking filter calibration failed!\n"); +end: return ret; } -- cgit v1.1 From 9c41d456e2936ea3aafa07d431c5963799f9659e Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 4 May 2008 18:18:48 -0300 Subject: V4L/DVB (7840): tda18271: make tda18271_set_standby_mode less verbose for basic debug Only show debug from tda18271_set_standby_mode if DBG_ADV is set. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-common.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c index 9001d42..d6938fc 100644 --- a/drivers/media/common/tuners/tda18271-common.c +++ b/drivers/media/common/tuners/tda18271-common.c @@ -486,7 +486,8 @@ int tda18271_set_standby_mode(struct dvb_frontend *fe, struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; - tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt); + if (tda18271_debug & DBG_ADV) + tda_dbg("sm = %d, sm_lt = %d, sm_xt = %d\n", sm, sm_lt, sm_xt); regs[R_EP3] &= ~0xe0; /* clear sm, sm_lt, sm_xt */ regs[R_EP3] |= sm ? (1 << 7) : 0 | -- cgit v1.1 From 31940e3966b6cf3bb3e535ffa1cb97b16edd555b Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 4 May 2008 19:37:27 -0300 Subject: V4L/DVB (7841): tda18271: fix error handling in tda18271_channel_configuration Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 3f7ca45..2c1bb38 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -51,6 +51,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; + int ret; u32 N; /* update TV broadcast parameters */ @@ -85,7 +86,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, /* update rf top / if top */ regs[R_EB22] = 0x00; regs[R_EB22] |= map->rfagc_top; - tda18271_write_regs(fe, R_EB22, 1); + ret = tda18271_write_regs(fe, R_EB22, 1); + if (ret < 0) + goto fail; /* --------------------------------------------------------------- */ @@ -121,7 +124,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, /* agc1 has priority on agc2 */ regs[R_EB1] &= ~0x01; - tda18271_write_regs(fe, R_EB1, 1); + ret = tda18271_write_regs(fe, R_EB1, 1); + if (ret < 0) + goto fail; /* --------------------------------------------------------------- */ @@ -141,7 +146,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, break; } - tda18271_write_regs(fe, R_TM, 7); + ret = tda18271_write_regs(fe, R_TM, 7); + if (ret < 0) + goto fail; /* force charge pump source */ charge_pump_source(fe, 1); @@ -158,9 +165,9 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, regs[R_EP3] &= ~0x04; else regs[R_EP3] |= 0x04; - tda18271_write_regs(fe, R_EP3, 1); - - return 0; + ret = tda18271_write_regs(fe, R_EP3, 1); +fail: + return ret; } static int tda18271_read_thermometer(struct dvb_frontend *fe) @@ -813,7 +820,7 @@ static int tda18271_tune(struct dvb_frontend *fe, tda18271c2_rf_tracking_filters_correction(fe, freq); break; } - tda18271_channel_configuration(fe, map, freq, bw); + ret = tda18271_channel_configuration(fe, map, freq, bw); mutex_unlock(&priv->lock); fail: -- cgit v1.1 From 20f4206379260e3ca02c8ee57bc3da9b0c7d09da Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 4 May 2008 19:57:06 -0300 Subject: V4L/DVB (7842): tda18271: fix error handling in tda18271c2_rf_tracking_filters_correction Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 2c1bb38..8b44d4c 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -220,11 +220,13 @@ static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe, struct tda18271_priv *priv = fe->tuner_priv; struct tda18271_rf_tracking_filter_cal *map = priv->rf_cal_state; unsigned char *regs = priv->tda18271_regs; - int tm_current, rfcal_comp, approx, i; + int tm_current, rfcal_comp, approx, i, ret; u8 dc_over_dt, rf_tab; /* power up */ - tda18271_set_standby_mode(fe, 0, 0, 0); + ret = tda18271_set_standby_mode(fe, 0, 0, 0); + if (ret < 0) + goto fail; /* read die current temperature */ tm_current = tda18271_read_thermometer(fe); @@ -257,9 +259,9 @@ static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe, rfcal_comp = dc_over_dt * (tm_current - priv->tm_rfcal); regs[R_EB14] = approx + rfcal_comp; - tda18271_write_regs(fe, R_EB14, 1); - - return 0; + ret = tda18271_write_regs(fe, R_EB14, 1); +fail: + return ret; } static int tda18271_por(struct dvb_frontend *fe) -- cgit v1.1 From 10ed0bf4af00c25590e8bfca344d8dec5c3637ae Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 4 May 2008 20:26:47 -0300 Subject: V4L/DVB (7843): tda18271: fix error handling in tda18271c1_rf_tracking_filter_calibration Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-fe.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 8b44d4c..13d651c 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -665,6 +665,7 @@ static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe, { struct tda18271_priv *priv = fe->tuner_priv; unsigned char *regs = priv->tda18271_regs; + int ret; u32 N = 0; /* calculate bp filter */ @@ -713,7 +714,10 @@ static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe, tda18271_calc_main_pll(fe, N); - tda18271_write_regs(fe, R_EP3, 11); + ret = tda18271_write_regs(fe, R_EP3, 11); + if (ret < 0) + return ret; + msleep(5); /* RF tracking filter calibration initialization */ /* search for K,M,CO for RF calibration */ -- cgit v1.1 From 4bd5d1071ddbb35ae545c7738e6411e50ce28b17 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 4 May 2008 21:32:21 -0300 Subject: V4L/DVB (7844): tda18271: add tda_fail macro to log error cases Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/tda18271-common.c | 14 +++---- drivers/media/common/tuners/tda18271-fe.c | 56 +++++++++++++-------------- drivers/media/common/tuners/tda18271-priv.h | 9 +++++ 3 files changed, 44 insertions(+), 35 deletions(-) diff --git a/drivers/media/common/tuners/tda18271-common.c b/drivers/media/common/tuners/tda18271-common.c index d6938fc..42b5f5d 100644 --- a/drivers/media/common/tuners/tda18271-common.c +++ b/drivers/media/common/tuners/tda18271-common.c @@ -508,7 +508,7 @@ int tda18271_calc_main_pll(struct dvb_frontend *fe, u32 freq) u32 div; int ret = tda18271_lookup_pll_map(fe, MAIN_PLL, &freq, &pd, &d); - if (ret < 0) + if (tda_fail(ret)) goto fail; regs[R_MPD] = (0x77 & pd); @@ -540,7 +540,7 @@ int tda18271_calc_cal_pll(struct dvb_frontend *fe, u32 freq) u32 div; int ret = tda18271_lookup_pll_map(fe, CAL_PLL, &freq, &pd, &d); - if (ret < 0) + if (tda_fail(ret)) goto fail; regs[R_CPD] = pd; @@ -564,7 +564,7 @@ int tda18271_calc_bp_filter(struct dvb_frontend *fe, u32 *freq) u8 val; int ret = tda18271_lookup_map(fe, BP_FILTER, freq, &val); - if (ret < 0) + if (tda_fail(ret)) goto fail; regs[R_EP1] &= ~0x07; /* clear bp filter bits */ @@ -581,7 +581,7 @@ int tda18271_calc_km(struct dvb_frontend *fe, u32 *freq) u8 val; int ret = tda18271_lookup_map(fe, RF_CAL_KMCO, freq, &val); - if (ret < 0) + if (tda_fail(ret)) goto fail; regs[R_EB13] &= ~0x7c; /* clear k & m bits */ @@ -598,7 +598,7 @@ int tda18271_calc_rf_band(struct dvb_frontend *fe, u32 *freq) u8 val; int ret = tda18271_lookup_map(fe, RF_BAND, freq, &val); - if (ret < 0) + if (tda_fail(ret)) goto fail; regs[R_EP2] &= ~0xe0; /* clear rf band bits */ @@ -615,7 +615,7 @@ int tda18271_calc_gain_taper(struct dvb_frontend *fe, u32 *freq) u8 val; int ret = tda18271_lookup_map(fe, GAIN_TAPER, freq, &val); - if (ret < 0) + if (tda_fail(ret)) goto fail; regs[R_EP2] &= ~0x1f; /* clear gain taper bits */ @@ -632,7 +632,7 @@ int tda18271_calc_ir_measure(struct dvb_frontend *fe, u32 *freq) u8 val; int ret = tda18271_lookup_map(fe, IR_MEASURE, freq, &val); - if (ret < 0) + if (tda_fail(ret)) goto fail; regs[R_EP5] &= ~0x07; diff --git a/drivers/media/common/tuners/tda18271-fe.c b/drivers/media/common/tuners/tda18271-fe.c index 13d651c..89c01fb 100644 --- a/drivers/media/common/tuners/tda18271-fe.c +++ b/drivers/media/common/tuners/tda18271-fe.c @@ -87,7 +87,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, regs[R_EB22] = 0x00; regs[R_EB22] |= map->rfagc_top; ret = tda18271_write_regs(fe, R_EB22, 1); - if (ret < 0) + if (tda_fail(ret)) goto fail; /* --------------------------------------------------------------- */ @@ -125,7 +125,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, regs[R_EB1] &= ~0x01; ret = tda18271_write_regs(fe, R_EB1, 1); - if (ret < 0) + if (tda_fail(ret)) goto fail; /* --------------------------------------------------------------- */ @@ -147,7 +147,7 @@ static int tda18271_channel_configuration(struct dvb_frontend *fe, } ret = tda18271_write_regs(fe, R_TM, 7); - if (ret < 0) + if (tda_fail(ret)) goto fail; /* force charge pump source */ @@ -225,7 +225,7 @@ static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe, /* power up */ ret = tda18271_set_standby_mode(fe, 0, 0, 0); - if (ret < 0) + if (tda_fail(ret)) goto fail; /* read die current temperature */ @@ -237,8 +237,8 @@ static int tda18271c2_rf_tracking_filters_correction(struct dvb_frontend *fe, rf_tab = regs[R_EB14]; i = tda18271_lookup_rf_band(fe, &freq, NULL); - if (i < 0) - return -EINVAL; + if (tda_fail(i)) + return i; if ((0 == map[i].rf3) || (freq / 1000 < map[i].rf2)) { approx = map[i].rf_a1 * @@ -273,20 +273,20 @@ static int tda18271_por(struct dvb_frontend *fe) /* power up detector 1 */ regs[R_EB12] &= ~0x20; ret = tda18271_write_regs(fe, R_EB12, 1); - if (ret < 0) + if (tda_fail(ret)) goto fail; regs[R_EB18] &= ~0x80; /* turn agc1 loop on */ regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */ ret = tda18271_write_regs(fe, R_EB18, 1); - if (ret < 0) + if (tda_fail(ret)) goto fail; regs[R_EB21] |= 0x03; /* set agc2_gain to -6 dB */ /* POR mode */ ret = tda18271_set_standby_mode(fe, 1, 0, 0); - if (ret < 0) + if (tda_fail(ret)) goto fail; /* disable 1.5 MHz low pass filter */ @@ -438,7 +438,7 @@ static int tda18271_powerscan(struct dvb_frontend *fe, /* read power detection info, stored in EB10 */ ret = tda18271_read_extended(fe); - if (ret < 0) + if (tda_fail(ret)) return ret; /* algorithm initialization */ @@ -466,7 +466,7 @@ static int tda18271_powerscan(struct dvb_frontend *fe, /* read power detection info, stored in EB10 */ ret = tda18271_read_extended(fe); - if (ret < 0) + if (tda_fail(ret)) return ret; count += 200; @@ -511,12 +511,12 @@ static int tda18271_powerscan_init(struct dvb_frontend *fe) regs[R_EP4] &= ~0x1c; /* clear if level bits */ ret = tda18271_write_regs(fe, R_EP3, 2); - if (ret < 0) + if (tda_fail(ret)) goto fail; regs[R_EB18] &= ~0x03; /* set agc1_gain to 6 dB */ ret = tda18271_write_regs(fe, R_EB18, 1); - if (ret < 0) + if (tda_fail(ret)) goto fail; regs[R_EB21] &= ~0x03; /* set agc2_gain to -15 dB */ @@ -546,7 +546,7 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq) i = tda18271_lookup_rf_band(fe, &freq, NULL); - if (i < 0) + if (tda_fail(i)) return i; rf_default[RF1] = 1000 * map[i].rf1_def; @@ -560,7 +560,7 @@ static int tda18271_rf_tracking_filters_init(struct dvb_frontend *fe, u32 freq) /* look for optimized calibration frequency */ bcal = tda18271_powerscan(fe, &rf_default[rf], &rf_freq[rf]); - if (bcal < 0) + if (tda_fail(bcal)) return bcal; tda18271_calc_rf_cal(fe, &rf_freq[rf]); @@ -610,7 +610,7 @@ static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe) msleep(200); ret = tda18271_powerscan_init(fe); - if (ret < 0) + if (tda_fail(ret)) goto fail; /* rf band calibration */ @@ -618,7 +618,7 @@ static int tda18271_calc_rf_filter_curve(struct dvb_frontend *fe) ret = tda18271_rf_tracking_filters_init(fe, 1000 * priv->rf_cal_state[i].rfmax); - if (ret < 0) + if (tda_fail(ret)) goto fail; } @@ -643,11 +643,11 @@ static int tda18271c2_rf_cal_init(struct dvb_frontend *fe) return 0; ret = tda18271_calc_rf_filter_curve(fe); - if (ret < 0) + if (tda_fail(ret)) goto fail; ret = tda18271_por(fe); - if (ret < 0) + if (tda_fail(ret)) goto fail; tda_info("tda18271: RF tracking filter calibration complete\n"); @@ -715,7 +715,7 @@ static int tda18271c1_rf_tracking_filter_calibration(struct dvb_frontend *fe, tda18271_calc_main_pll(fe, N); ret = tda18271_write_regs(fe, R_EP3, 11); - if (ret < 0) + if (tda_fail(ret)) return ret; msleep(5); /* RF tracking filter calibration initialization */ @@ -768,7 +768,7 @@ static int tda18271_ir_cal_init(struct dvb_frontend *fe) int ret; ret = tda18271_read_regs(fe); - if (ret < 0) + if (tda_fail(ret)) goto fail; /* test IR_CAL_OK to see if we need init */ @@ -787,12 +787,12 @@ static int tda18271_init(struct dvb_frontend *fe) /* power up */ ret = tda18271_set_standby_mode(fe, 0, 0, 0); - if (ret < 0) + if (tda_fail(ret)) goto fail; /* initialization */ ret = tda18271_ir_cal_init(fe); - if (ret < 0) + if (tda_fail(ret)) goto fail; if (priv->id == TDA18271HDC2) @@ -813,7 +813,7 @@ static int tda18271_tune(struct dvb_frontend *fe, freq, map->if_freq, bw, map->agc_mode, map->std); ret = tda18271_init(fe); - if (ret < 0) + if (tda_fail(ret)) goto fail; mutex_lock(&priv->lock); @@ -894,7 +894,7 @@ static int tda18271_set_params(struct dvb_frontend *fe, ret = tda18271_tune(fe, map, freq, bw); - if (ret < 0) + if (tda_fail(ret)) goto fail; priv->frequency = freq; @@ -950,7 +950,7 @@ static int tda18271_set_analog_params(struct dvb_frontend *fe, ret = tda18271_tune(fe, map, freq, 0); - if (ret < 0) + if (tda_fail(ret)) goto fail; priv->frequency = freq; @@ -1153,10 +1153,10 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr, if (cfg) priv->small_i2c = cfg->small_i2c; - if (tda18271_get_id(fe) < 0) + if (tda_fail(tda18271_get_id(fe))) goto fail; - if (tda18271_assign_map_layout(fe) < 0) + if (tda_fail(tda18271_assign_map_layout(fe))) goto fail; mutex_lock(&priv->lock); diff --git a/drivers/media/common/tuners/tda18271-priv.h b/drivers/media/common/tuners/tda18271-priv.h index 2bc5eb3..81a7393 100644 --- a/drivers/media/common/tuners/tda18271-priv.h +++ b/drivers/media/common/tuners/tda18271-priv.h @@ -153,6 +153,15 @@ extern int tda18271_debug; #define tda_reg(fmt, arg...) dprintk(KERN_DEBUG, DBG_REG, fmt, ##arg) #define tda_cal(fmt, arg...) dprintk(KERN_DEBUG, DBG_CAL, fmt, ##arg) +#define tda_fail(ret) \ +({ \ + int __ret; \ + __ret = (ret < 0); \ + if (__ret) \ + tda_printk(KERN_ERR, "error %d on line %d\n", ret, __LINE__);\ + __ret; \ +}) + /*---------------------------------------------------------------------*/ enum tda18271_map_type { -- cgit v1.1 From fdbbfb092cee0d826cba96df51f56c0e22cae579 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 6 May 2008 12:35:58 -0300 Subject: V4L/DVB (7846): Re-creates VIDEO_TUNER VIDEO_TUNER is responsible for compilation of tuners.ko module. This were the previous behaviour before the creation of MEDIA_TUNER. Before this patch, tuner.ko were created even for drivers that don't need a tuner (like webcam drivers). Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 6 +++++- drivers/media/video/Makefile | 2 +- drivers/media/video/bt8xx/Kconfig | 2 +- drivers/media/video/cx18/Kconfig | 2 +- drivers/media/video/cx23885/Kconfig | 2 +- drivers/media/video/cx88/Kconfig | 2 +- drivers/media/video/em28xx/Kconfig | 2 +- drivers/media/video/ivtv/Kconfig | 2 +- drivers/media/video/pvrusb2/Kconfig | 2 +- drivers/media/video/saa7134/Kconfig | 2 +- drivers/media/video/usbvision/Kconfig | 2 +- 11 files changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 98e2e1a2..89d8d37 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -44,6 +44,10 @@ config VIDEO_TVEEPROM tristate depends on I2C +config VIDEO_TUNER + tristate + depends on MEDIA_TUNER + # # Multimedia Video device configuration # @@ -690,7 +694,7 @@ config VIDEO_MXB tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" depends on PCI && VIDEO_V4L1 && I2C select VIDEO_SAA7146_VV - select MEDIA_TUNER + select VIDEO_TUNER select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index a352c6e..dff0d6a 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -84,7 +84,7 @@ obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o obj-$(CONFIG_VIDEO_DPC) += dpc7146.o obj-$(CONFIG_TUNER_3036) += tuner-3036.o -obj-$(CONFIG_MEDIA_TUNER) += tuner.o +obj-$(CONFIG_VIDEO_TUNER) += tuner.o obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig index 7431ef6..cfc822bb 100644 --- a/drivers/media/video/bt8xx/Kconfig +++ b/drivers/media/video/bt8xx/Kconfig @@ -6,7 +6,7 @@ config VIDEO_BT848 select VIDEO_BTCX select VIDEOBUF_DMA_SG select VIDEO_IR - select MEDIA_TUNER + select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index acc4b47..be654a2 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig @@ -4,7 +4,7 @@ config VIDEO_CX18 select I2C_ALGOBIT select FW_LOADER select VIDEO_IR - select MEDIA_TUNER + select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_CX2341X select VIDEO_CS5345 diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index 013e18c..491a005 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -4,7 +4,7 @@ config VIDEO_CX23885 select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX - select MEDIA_TUNER + select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_IR select VIDEOBUF_DVB diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index b0d7d6a..f1e7991 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -5,7 +5,7 @@ config VIDEO_CX88 select FW_LOADER select VIDEO_BTCX select VIDEOBUF_DMA_SG - select MEDIA_TUNER + select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_IR select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index c7c2896..9caffed 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -1,7 +1,7 @@ config VIDEO_EM28XX tristate "Empia EM28xx USB video capture support" depends on VIDEO_DEV && I2C && INPUT - select MEDIA_TUNER + select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_IR select VIDEOBUF_VMALLOC diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index eec115b..b617170 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig @@ -4,7 +4,7 @@ config VIDEO_IVTV select I2C_ALGOBIT select FW_LOADER select VIDEO_IR - select MEDIA_TUNER + select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_CX2341X select VIDEO_CX25840 diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index 9620c67..31634f6 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig @@ -2,7 +2,7 @@ config VIDEO_PVRUSB2 tristate "Hauppauge WinTV-PVR USB2 support" depends on VIDEO_V4L2 && I2C select FW_LOADER - select MEDIA_TUNER + select VIDEO_TUNER select VIDEO_TVEEPROM select VIDEO_CX2341X select VIDEO_SAA711X diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index 40e4c3b..dbdfbaa 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -3,7 +3,7 @@ config VIDEO_SAA7134 depends on VIDEO_DEV && PCI && I2C && INPUT select VIDEOBUF_DMA_SG select VIDEO_IR - select MEDIA_TUNER + select VIDEO_TUNER select VIDEO_TVEEPROM select CRC32 ---help--- diff --git a/drivers/media/video/usbvision/Kconfig b/drivers/media/video/usbvision/Kconfig index 74e1d30..fc24ef0 100644 --- a/drivers/media/video/usbvision/Kconfig +++ b/drivers/media/video/usbvision/Kconfig @@ -1,7 +1,7 @@ config VIDEO_USBVISION tristate "USB video devices based on Nogatech NT1003/1004/1005" depends on I2C && VIDEO_V4L2 - select MEDIA_TUNER + select VIDEO_TUNER select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO ---help--- There are more than 50 different USB video devices based on -- cgit v1.1 From 3929c0f9acc62a2fee99387b3cb58fd2a3668cd3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 6 May 2008 12:38:24 -0300 Subject: V4L/DVB (7847): Simplifies Kconfig rules Since all tuners are dependent of I2C, move I2C dependency to MEDIA_TUNER. Also, simplifies the dependencies for the other Kconfig items. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/Kconfig | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index c0b472e..ecbccc3 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig @@ -19,8 +19,8 @@ config MEDIA_ATTACH config MEDIA_TUNER tristate - default DVB_CORE || VIDEO_DEV - depends on DVB_CORE || VIDEO_DEV + default VIDEO_MEDIA && I2C + depends on VIDEO_MEDIA && I2C select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE @@ -46,7 +46,6 @@ if MEDIA_TUNER_CUSTOMIZE config MEDIA_TUNER_SIMPLE tristate "Simple tuner support" - depends on I2C select MEDIA_TUNER_TDA9887 default m if MEDIA_TUNER_CUSTOMIZE help @@ -54,7 +53,6 @@ config MEDIA_TUNER_SIMPLE config MEDIA_TUNER_TDA8290 tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo" - depends on I2C select MEDIA_TUNER_TDA827X select MEDIA_TUNER_TDA18271 default m if MEDIA_TUNER_CUSTOMIZE @@ -63,21 +61,18 @@ config MEDIA_TUNER_TDA8290 config MEDIA_TUNER_TDA827X tristate "Philips TDA827X silicon tuner" - depends on DVB_CORE && I2C default m if DVB_FE_CUSTOMISE help A DVB-T silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA18271 tristate "NXP TDA18271 silicon tuner" - depends on I2C default m if DVB_FE_CUSTOMISE help A silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA9887 tristate "TDA 9885/6/7 analog IF demodulator" - depends on I2C default m if MEDIA_TUNER_CUSTOMIZE help Say Y here to include support for Philips TDA9885/6/7 @@ -85,63 +80,56 @@ config MEDIA_TUNER_TDA9887 config MEDIA_TUNER_TEA5761 tristate "TEA 5761 radio tuner (EXPERIMENTAL)" - depends on I2C && EXPERIMENTAL + depends on EXPERIMENTAL default m if MEDIA_TUNER_CUSTOMIZE help Say Y here to include support for the Philips TEA5761 radio tuner. config MEDIA_TUNER_TEA5767 tristate "TEA 5767 radio tuner" - depends on I2C default m if MEDIA_TUNER_CUSTOMIZE help Say Y here to include support for the Philips TEA5767 radio tuner. config MEDIA_TUNER_MT20XX tristate "Microtune 2032 / 2050 tuners" - depends on I2C default m if MEDIA_TUNER_CUSTOMIZE help Say Y here to include support for the MT2032 / MT2050 tuner. config MEDIA_TUNER_MT2060 tristate "Microtune MT2060 silicon IF tuner" - depends on I2C default m if DVB_FE_CUSTOMISE help A driver for the silicon IF tuner MT2060 from Microtune. config MEDIA_TUNER_MT2266 tristate "Microtune MT2266 silicon tuner" - depends on I2C default m if DVB_FE_CUSTOMISE help A driver for the silicon baseband tuner MT2266 from Microtune. config MEDIA_TUNER_MT2131 tristate "Microtune MT2131 silicon tuner" - depends on I2C default m if DVB_FE_CUSTOMISE help A driver for the silicon baseband tuner MT2131 from Microtune. config MEDIA_TUNER_QT1010 tristate "Quantek QT1010 silicon tuner" - depends on DVB_CORE && I2C default m if DVB_FE_CUSTOMISE help A driver for the silicon tuner QT1010 from Quantek. config MEDIA_TUNER_XC2028 tristate "XCeive xc2028/xc3028 tuners" - depends on I2C && FW_LOADER + depends on FW_LOADER default m if MEDIA_TUNER_CUSTOMIZE help Say Y here to include support for the xc2028/xc3028 tuners. config MEDIA_TUNER_XC5000 tristate "Xceive XC5000 silicon tuner" - depends on I2C select FW_LOADER default m if DVB_FE_CUSTOMISE help -- cgit v1.1 From eabcaf32041fcd04672049e76124bd4cd63b1cbf Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 6 May 2008 13:44:03 -0300 Subject: V4L/DVB (7848): Fix dependencies for tuner-xc2028 and em28xx-dvb em28xx-dvb doesn't need FW_LOADER. Instead, tuner-xc2028 needs to select FW_LOADER. Also, this can happen only if HOTPLUG is selected, since FW_LOADER is dependent on HOTPLUG. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/Kconfig | 5 +++-- drivers/media/video/em28xx/Kconfig | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index ecbccc3..4fb77bc 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig @@ -21,7 +21,7 @@ config MEDIA_TUNER tristate default VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C - select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE @@ -123,7 +123,8 @@ config MEDIA_TUNER_QT1010 config MEDIA_TUNER_XC2028 tristate "XCeive xc2028/xc3028 tuners" - depends on FW_LOADER + depends on HOTPLUG + select FW_LOADER default m if MEDIA_TUNER_CUSTOMIZE help Say Y here to include support for the xc2028/xc3028 tuners. diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 9caffed..16a5af3 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -35,7 +35,6 @@ config VIDEO_EM28XX_DVB select DVB_LGDT330X if !DVB_FE_CUSTOMISE select DVB_ZL10353 if !DVB_FE_CUSTOMISE select VIDEOBUF_DVB - select FW_LOADER ---help--- This adds support for DVB cards based on the Empiatech em28xx chips. -- cgit v1.1 From ec44c9aed0eddceaef3c6b4d23f6d7702ec57b4d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 6 May 2008 13:46:12 -0300 Subject: V4L/DVB (7849): cx88: fix Kconfig depencencies for FW_LOADER cx88 doesn't need support for FW_LOADER. Instead, this is required only for cx88-blackbird. Also, cx88-blackbird depends on HOTPLUG, due to FW_LOADER dependency. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/cx88/Kconfig b/drivers/media/video/cx88/Kconfig index f1e7991..10e20d8 100644 --- a/drivers/media/video/cx88/Kconfig +++ b/drivers/media/video/cx88/Kconfig @@ -2,7 +2,6 @@ config VIDEO_CX88 tristate "Conexant 2388x (bt878 successor) support" depends on VIDEO_DEV && PCI && I2C && INPUT select I2C_ALGOBIT - select FW_LOADER select VIDEO_BTCX select VIDEOBUF_DMA_SG select VIDEO_TUNER @@ -34,8 +33,9 @@ config VIDEO_CX88_ALSA config VIDEO_CX88_BLACKBIRD tristate "Blackbird MPEG encoder support (cx2388x + cx23416)" - depends on VIDEO_CX88 + depends on VIDEO_CX88 && HOTPLUG select VIDEO_CX2341X + select FW_LOADER ---help--- This adds support for MPEG encoder cards based on the Blackbird reference design, using the Conexant 2388x -- cgit v1.1 From 755a18baad393836c88ce92c3b7198c70e2e3205 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 6 May 2008 14:09:01 -0300 Subject: V4L/DVB (7851): Fix FW_LOADER depencency at v4l/dvb Since: 1) FW_LOADER is defined as: config FW_LOADER tristate "Userspace firmware loading support" depends on HOTPLUG 2) several V4L/DVB driver just selects it; 3) select is not smart enough to auto-select HOTPLUG, if select FW_LOADER. So, All drivers that select FW_LOADER should also depend on HOTPLUG. An easier solution (for the end-user perspective) would be to "select HOTPLUG". However, live is not simple. This would cause recursive dependency issues like this one: drivers/usb/Kconfig:62:error: found recursive dependency: USB -> USB_OHCI_HCD -> I2C -> MEDIA_TUNER -> MEDIA_TUNER_XC2028 -> HOTPLUG -> PCCARD -> PCMCIA -> USB_ARCH_HAS_HCD -> MOUSE_APPLETOUCH -> USB Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/Kconfig | 1 + drivers/media/dvb/bt8xx/Kconfig | 1 + drivers/media/dvb/dvb-usb/Kconfig | 1 + drivers/media/dvb/frontends/Kconfig | 16 ++++++++-------- drivers/media/dvb/ttpci/Kconfig | 2 ++ drivers/media/dvb/ttusb-dec/Kconfig | 1 + drivers/media/video/bt8xx/Kconfig | 1 + drivers/media/video/cx18/Kconfig | 2 ++ drivers/media/video/cx23885/Kconfig | 1 + drivers/media/video/cx25840/Kconfig | 1 + drivers/media/video/ivtv/Kconfig | 2 ++ drivers/media/video/pvrusb2/Kconfig | 1 + drivers/media/video/saa7134/Kconfig | 1 + 13 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index 4fb77bc..10f12ba 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig @@ -131,6 +131,7 @@ config MEDIA_TUNER_XC2028 config MEDIA_TUNER_XC5000 tristate "Xceive XC5000 silicon tuner" + depends on HOTPLUG select FW_LOADER default m if DVB_FE_CUSTOMISE help diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig index d1239b8..7588db1 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig @@ -1,6 +1,7 @@ config DVB_BT8XX tristate "BT8xx based PCI cards" depends on DVB_CORE && PCI && I2C && VIDEO_BT848 + depends on HOTPLUG # due to FW_LOADER select DVB_MT352 if !DVB_FE_CUSTOMISE select DVB_SP887X if !DVB_FE_CUSTOMISE select DVB_NXT6000 if !DVB_FE_CUSTOMISE diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index 4c1cff9..cf4584e 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -1,6 +1,7 @@ config DVB_USB tristate "Support for various USB DVB devices" depends on DVB_CORE && USB && I2C + depends on HOTPLUG # due to FW_LOADER select FW_LOADER help By enabling this you will be able to choose the various supported diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 6d23846..47d0215 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -97,7 +97,7 @@ comment "DVB-T (terrestrial) frontends" config DVB_SP8870 tristate "Spase sp8870 based" - depends on DVB_CORE && I2C + depends on DVB_CORE && I2C && HOTPLUG default m if DVB_FE_CUSTOMISE select FW_LOADER help @@ -110,7 +110,7 @@ config DVB_SP8870 config DVB_SP887X tristate "Spase sp887x based" - depends on DVB_CORE && I2C + depends on DVB_CORE && I2C && HOTPLUG default m if DVB_FE_CUSTOMISE select FW_LOADER help @@ -144,7 +144,7 @@ config DVB_L64781 config DVB_TDA1004X tristate "Philips TDA10045H/TDA10046H based" - depends on DVB_CORE && I2C + depends on DVB_CORE && I2C && HOTPLUG default m if DVB_FE_CUSTOMISE select FW_LOADER help @@ -211,7 +211,7 @@ config DVB_DIB7000P config DVB_TDA10048 tristate "Philips TDA10048HN based" - depends on DVB_CORE && I2C + depends on DVB_CORE && I2C && HOTPLUG default m if DVB_FE_CUSTOMISE select FW_LOADER help @@ -253,7 +253,7 @@ comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends" config DVB_NXT200X tristate "NxtWave Communications NXT2002/NXT2004 based" - depends on DVB_CORE && I2C + depends on DVB_CORE && I2C && HOTPLUG default m if DVB_FE_CUSTOMISE select FW_LOADER help @@ -268,7 +268,7 @@ config DVB_NXT200X config DVB_OR51211 tristate "Oren OR51211 based" - depends on DVB_CORE && I2C + depends on DVB_CORE && I2C && HOTPLUG default m if DVB_FE_CUSTOMISE select FW_LOADER help @@ -281,7 +281,7 @@ config DVB_OR51211 config DVB_OR51132 tristate "Oren OR51132 based" - depends on DVB_CORE && I2C + depends on DVB_CORE && I2C && HOTPLUG default m if DVB_FE_CUSTOMISE select FW_LOADER help @@ -297,7 +297,7 @@ config DVB_OR51132 config DVB_BCM3510 tristate "Broadcom BCM3510" - depends on DVB_CORE && I2C + depends on DVB_CORE && I2C && HOTPLUG default m if DVB_FE_CUSTOMISE select FW_LOADER help diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index ae882432..d4339b1 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -5,6 +5,7 @@ config TTPCI_EEPROM config DVB_AV7110 tristate "AV7110 cards" depends on DVB_CORE && PCI && I2C + depends on HOTPLUG select FW_LOADER if !DVB_AV7110_FIRMWARE select TTPCI_EEPROM select VIDEO_SAA7146_VV @@ -123,6 +124,7 @@ config DVB_BUDGET_AV depends on DVB_BUDGET_CORE && I2C select VIDEO_SAA7146_VV depends on VIDEO_DEV # dependencies of VIDEO_SAA7146_VV + depends on HOTPLUG # dependency of FW_LOADER select DVB_PLL if !DVB_FE_CUSTOMISE select DVB_STV0299 if !DVB_FE_CUSTOMISE select DVB_TDA1004X if !DVB_FE_CUSTOMISE diff --git a/drivers/media/dvb/ttusb-dec/Kconfig b/drivers/media/dvb/ttusb-dec/Kconfig index 8361101..0712899 100644 --- a/drivers/media/dvb/ttusb-dec/Kconfig +++ b/drivers/media/dvb/ttusb-dec/Kconfig @@ -1,6 +1,7 @@ config DVB_TTUSB_DEC tristate "Technotrend/Hauppauge USB DEC devices" depends on DVB_CORE && USB + depends on HOTPLUG # due to FW_LOADER select FW_LOADER select CRC32 help diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig index cfc822bb..24a34fc 100644 --- a/drivers/media/video/bt8xx/Kconfig +++ b/drivers/media/video/bt8xx/Kconfig @@ -1,6 +1,7 @@ config VIDEO_BT848 tristate "BT848 Video For Linux" depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 && INPUT + depends on HOTPLUG # due to FW_LOADER select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index be654a2..35a5599 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig @@ -1,6 +1,8 @@ config VIDEO_CX18 tristate "Conexant cx23418 MPEG encoder support" depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL + depends on INPUT # due to VIDEO_IR + depends on HOTPLUG # due to FW_LOADER select I2C_ALGOBIT select FW_LOADER select VIDEO_IR diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index 491a005..7bf14c9 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -1,6 +1,7 @@ config VIDEO_CX23885 tristate "Conexant cx23885 (2388x successor) support" depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT + depends on HOTPLUG # due to FW_LOADER select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX diff --git a/drivers/media/video/cx25840/Kconfig b/drivers/media/video/cx25840/Kconfig index 7cf29a0..448f4cd 100644 --- a/drivers/media/video/cx25840/Kconfig +++ b/drivers/media/video/cx25840/Kconfig @@ -1,6 +1,7 @@ config VIDEO_CX25840 tristate "Conexant CX2584x audio/video decoders" depends on VIDEO_V4L2 && I2C && EXPERIMENTAL + depends on HOTPLUG # due to FW_LOADER select FW_LOADER ---help--- Support for the Conexant CX2584x audio/video decoders. diff --git a/drivers/media/video/ivtv/Kconfig b/drivers/media/video/ivtv/Kconfig index b617170..5d7ee8f 100644 --- a/drivers/media/video/ivtv/Kconfig +++ b/drivers/media/video/ivtv/Kconfig @@ -1,6 +1,8 @@ config VIDEO_IVTV tristate "Conexant cx23416/cx23415 MPEG encoder/decoder support" depends on VIDEO_V4L1 && VIDEO_V4L2 && PCI && I2C && EXPERIMENTAL + depends on INPUT # due to VIDEO_IR + depends on HOTPLUG # due to FW_LOADER select I2C_ALGOBIT select FW_LOADER select VIDEO_IR diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index 31634f6..e2a7a50 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig @@ -1,6 +1,7 @@ config VIDEO_PVRUSB2 tristate "Hauppauge WinTV-PVR USB2 support" depends on VIDEO_V4L2 && I2C + depends on HOTPLUG # due to FW_LOADER select FW_LOADER select VIDEO_TUNER select VIDEO_TVEEPROM diff --git a/drivers/media/video/saa7134/Kconfig b/drivers/media/video/saa7134/Kconfig index dbdfbaa..83f076a 100644 --- a/drivers/media/video/saa7134/Kconfig +++ b/drivers/media/video/saa7134/Kconfig @@ -27,6 +27,7 @@ config VIDEO_SAA7134_ALSA config VIDEO_SAA7134_DVB tristate "DVB/ATSC Support for saa7134 based TV cards" depends on VIDEO_SAA7134 && DVB_CORE + depends on HOTPLUG # due to FW_LOADER select VIDEOBUF_DVB select FW_LOADER select DVB_PLL if !DVB_FE_CUSTOMISE -- cgit v1.1 From feb5bce24ed4d90c0a5710a669072c778a2c5148 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 1 May 2008 09:22:13 -0300 Subject: V4L/DVB (7852): ivtv: prefix ivtv external functions with ivtv_ Fix conflict with cx18 driver. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-controls.c | 4 ++-- drivers/media/video/ivtv/ivtv-ioctl.c | 16 ++++++++-------- drivers/media/video/ivtv/ivtv-ioctl.h | 6 +++--- drivers/media/video/ivtv/ivtv-vbi.c | 3 ++- 4 files changed, 15 insertions(+), 14 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-controls.c b/drivers/media/video/ivtv/ivtv-controls.c index 8c02fa6..c7e449f 100644 --- a/drivers/media/video/ivtv/ivtv-controls.c +++ b/drivers/media/video/ivtv/ivtv-controls.c @@ -181,12 +181,12 @@ static int ivtv_setup_vbi_fmt(struct ivtv *itv, enum v4l2_mpeg_stream_vbi_fmt fm return 0; } /* Need sliced data for mpeg insertion */ - if (get_service_set(itv->vbi.sliced_in) == 0) { + if (ivtv_get_service_set(itv->vbi.sliced_in) == 0) { if (itv->is_60hz) itv->vbi.sliced_in->service_set = V4L2_SLICED_CAPTION_525; else itv->vbi.sliced_in->service_set = V4L2_SLICED_WSS_625; - expand_service_set(itv->vbi.sliced_in, itv->is_50hz); + ivtv_expand_service_set(itv->vbi.sliced_in, itv->is_50hz); } return 0; } diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index d508b5d..26cc0f6 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -38,7 +38,7 @@ #include #include -u16 service2vbi(int type) +u16 ivtv_service2vbi(int type) { switch (type) { case V4L2_SLICED_TELETEXT_B: @@ -88,7 +88,7 @@ static u16 select_service_from_set(int field, int line, u16 set, int is_pal) return 0; } -void expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) +void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) { u16 set = fmt->service_set; int f, l; @@ -115,7 +115,7 @@ static int check_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal) return set != 0; } -u16 get_service_set(struct v4l2_sliced_vbi_format *fmt) +u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt) { int f, l; u16 set = 0; @@ -466,7 +466,7 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm vbifmt->service_lines[0][23] = V4L2_SLICED_WSS_625; vbifmt->service_lines[0][16] = V4L2_SLICED_VPS; } - vbifmt->service_set = get_service_set(vbifmt); + vbifmt->service_set = ivtv_get_service_set(vbifmt); break; } @@ -481,12 +481,12 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) { vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525; - expand_service_set(vbifmt, itv->is_50hz); + ivtv_expand_service_set(vbifmt, itv->is_50hz); break; } itv->video_dec_func(itv, VIDIOC_G_FMT, fmt); - vbifmt->service_set = get_service_set(vbifmt); + vbifmt->service_set = ivtv_get_service_set(vbifmt); break; } case V4L2_BUF_TYPE_VBI_OUTPUT: @@ -640,9 +640,9 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, memset(vbifmt->reserved, 0, sizeof(vbifmt->reserved)); if (vbifmt->service_set) - expand_service_set(vbifmt, itv->is_50hz); + ivtv_expand_service_set(vbifmt, itv->is_50hz); set = check_service_set(vbifmt, itv->is_50hz); - vbifmt->service_set = get_service_set(vbifmt); + vbifmt->service_set = ivtv_get_service_set(vbifmt); if (!set_fmt) return 0; diff --git a/drivers/media/video/ivtv/ivtv-ioctl.h b/drivers/media/video/ivtv/ivtv-ioctl.h index a03351b..4e67f0e 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.h +++ b/drivers/media/video/ivtv/ivtv-ioctl.h @@ -21,9 +21,9 @@ #ifndef IVTV_IOCTL_H #define IVTV_IOCTL_H -u16 service2vbi(int type); -void expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal); -u16 get_service_set(struct v4l2_sliced_vbi_format *fmt); +u16 ivtv_service2vbi(int type); +void ivtv_expand_service_set(struct v4l2_sliced_vbi_format *fmt, int is_pal); +u16 ivtv_get_service_set(struct v4l2_sliced_vbi_format *fmt); int ivtv_v4l2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg); int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void *arg); diff --git a/drivers/media/video/ivtv/ivtv-vbi.c b/drivers/media/video/ivtv/ivtv-vbi.c index c151bcf..71798f0 100644 --- a/drivers/media/video/ivtv/ivtv-vbi.c +++ b/drivers/media/video/ivtv/ivtv-vbi.c @@ -169,7 +169,8 @@ static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp) linemask[0] |= (1 << l); else linemask[1] |= (1 << (l - 32)); - dst[sd + 12 + line * 43] = service2vbi(itv->vbi.sliced_data[i].id); + dst[sd + 12 + line * 43] = + ivtv_service2vbi(itv->vbi.sliced_data[i].id); memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42); line++; } -- cgit v1.1 From 6a4a79355bfa9ae6977556595a68f2e3a0e143f7 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 1 May 2008 09:34:54 -0300 Subject: V4L/DVB (7853): ivtv/cx18: fix compile warnings Fix compile warnings if MODULE is not defined. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 4 ++++ drivers/media/video/ivtv/ivtv-driver.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 3f55d47..7813380 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -548,6 +548,7 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *dev, return 0; } +#ifdef MODULE static u32 cx18_request_module(struct cx18 *cx, u32 hw, const char *name, u32 id) { @@ -560,12 +561,14 @@ static u32 cx18_request_module(struct cx18 *cx, u32 hw, CX18_DEBUG_INFO("Loaded module %s\n", name); return hw; } +#endif static void cx18_load_and_init_modules(struct cx18 *cx) { u32 hw = cx->card->hw_all; int i; +#ifdef MODULE /* load modules */ #ifndef CONFIG_MEDIA_TUNER hw = cx18_request_module(cx, hw, "tuner", CX18_HW_TUNER); @@ -573,6 +576,7 @@ static void cx18_load_and_init_modules(struct cx18 *cx) #ifndef CONFIG_VIDEO_CS5345 hw = cx18_request_module(cx, hw, "cs5345", CX18_HW_CS5345); #endif +#endif /* check which i2c devices are actually found */ for (i = 0; i < 32; i++) { diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index ed020f7..a0756a9 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -853,6 +853,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev, return 0; } +#ifdef MODULE static u32 ivtv_request_module(struct ivtv *itv, u32 hw, const char *name, u32 id) { @@ -865,12 +866,14 @@ static u32 ivtv_request_module(struct ivtv *itv, u32 hw, IVTV_DEBUG_INFO("Loaded module %s\n", name); return hw; } +#endif static void ivtv_load_and_init_modules(struct ivtv *itv) { u32 hw = itv->card->hw_all; unsigned i; +#ifdef MODULE /* load modules */ #ifndef CONFIG_MEDIA_TUNER hw = ivtv_request_module(itv, hw, "tuner", IVTV_HW_TUNER); @@ -911,6 +914,7 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) #ifndef CONFIG_VIDEO_M52790 hw = ivtv_request_module(itv, hw, "m52790", IVTV_HW_M52790); #endif +#endif /* check which i2c devices are actually found */ for (i = 0; i < 32; i++) { -- cgit v1.1 From 3f98387efa9333c5765d36e144c47c107d6ba64a Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Thu, 1 May 2008 10:31:12 -0300 Subject: V4L/DVB (7854): cx18/ivtv: improve and fix out-of-memory handling - don't show kernel backtrace when the allocation of the buffers fails: the normal ivtv/cx18 messages are clear enough and the backtrace scares users. - fix cleanup after the buffer allocation fails (caused kernel panic). Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 4 ++-- drivers/media/video/cx18/cx18-queue.c | 6 +++--- drivers/media/video/cx18/cx18-streams.c | 13 ++++++++----- drivers/media/video/cx18/cx18-streams.h | 2 +- drivers/media/video/ivtv/ivtv-driver.c | 4 ++-- drivers/media/video/ivtv/ivtv-queue.c | 12 +++++++----- drivers/media/video/ivtv/ivtv-streams.c | 13 ++++++++----- drivers/media/video/ivtv/ivtv-streams.h | 2 +- drivers/media/video/ivtv/ivtv-yuv.c | 2 +- drivers/media/video/ivtv/ivtvfb.c | 6 ++++-- 10 files changed, 37 insertions(+), 27 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 7813380..9453223 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -805,7 +805,7 @@ static int __devinit cx18_probe(struct pci_dev *dev, return 0; free_streams: - cx18_streams_cleanup(cx); + cx18_streams_cleanup(cx, 1); free_irq: free_irq(cx->dev->irq, (void *)cx); free_i2c: @@ -908,7 +908,7 @@ static void cx18_remove(struct pci_dev *pci_dev) cx18_halt_firmware(cx); - cx18_streams_cleanup(cx); + cx18_streams_cleanup(cx, 1); exit_cx18_i2c(cx); diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index 65af1bb..4ef6996 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -239,12 +239,12 @@ int cx18_stream_alloc(struct cx18_stream *s) /* allocate stream buffers. Initially all buffers are in q_free. */ for (i = 0; i < s->buffers; i++) { - struct cx18_buffer *buf = - kzalloc(sizeof(struct cx18_buffer), GFP_KERNEL); + struct cx18_buffer *buf = kzalloc(sizeof(struct cx18_buffer), + GFP_KERNEL|__GFP_NOWARN); if (buf == NULL) break; - buf->buf = kmalloc(s->buf_size, GFP_KERNEL); + buf->buf = kmalloc(s->buf_size, GFP_KERNEL|__GFP_NOWARN); if (buf->buf == NULL) { kfree(buf); break; diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c index afb141b..4ca9d84 100644 --- a/drivers/media/video/cx18/cx18-streams.c +++ b/drivers/media/video/cx18/cx18-streams.c @@ -218,7 +218,7 @@ int cx18_streams_setup(struct cx18 *cx) return 0; /* One or more streams could not be initialized. Clean 'em all up. */ - cx18_streams_cleanup(cx); + cx18_streams_cleanup(cx, 0); return -ENOMEM; } @@ -296,12 +296,12 @@ int cx18_streams_register(struct cx18 *cx) return 0; /* One or more streams could not be initialized. Clean 'em all up. */ - cx18_streams_cleanup(cx); + cx18_streams_cleanup(cx, 1); return -ENOMEM; } /* Unregister v4l2 devices */ -void cx18_streams_cleanup(struct cx18 *cx) +void cx18_streams_cleanup(struct cx18 *cx, int unregister) { struct video_device *vdev; int type; @@ -319,8 +319,11 @@ void cx18_streams_cleanup(struct cx18 *cx) cx18_stream_free(&cx->streams[type]); - /* Unregister device */ - video_unregister_device(vdev); + /* Unregister or release device */ + if (unregister) + video_unregister_device(vdev); + else + video_device_release(vdev); } } diff --git a/drivers/media/video/cx18/cx18-streams.h b/drivers/media/video/cx18/cx18-streams.h index 8c7ba7d..f327e94 100644 --- a/drivers/media/video/cx18/cx18-streams.h +++ b/drivers/media/video/cx18/cx18-streams.h @@ -24,7 +24,7 @@ u32 cx18_find_handle(struct cx18 *cx); int cx18_streams_setup(struct cx18 *cx); int cx18_streams_register(struct cx18 *cx); -void cx18_streams_cleanup(struct cx18 *cx); +void cx18_streams_cleanup(struct cx18 *cx, int unregister); /* Capture related */ int cx18_start_v4l2_encode_stream(struct cx18_stream *s); diff --git a/drivers/media/video/ivtv/ivtv-driver.c b/drivers/media/video/ivtv/ivtv-driver.c index a0756a9..797e636 100644 --- a/drivers/media/video/ivtv/ivtv-driver.c +++ b/drivers/media/video/ivtv/ivtv-driver.c @@ -1232,7 +1232,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, return 0; free_streams: - ivtv_streams_cleanup(itv); + ivtv_streams_cleanup(itv, 1); free_irq: free_irq(itv->dev->irq, (void *)itv); free_i2c: @@ -1377,7 +1377,7 @@ static void ivtv_remove(struct pci_dev *pci_dev) flush_workqueue(itv->irq_work_queues); destroy_workqueue(itv->irq_work_queues); - ivtv_streams_cleanup(itv); + ivtv_streams_cleanup(itv, 1); ivtv_udma_free(itv); exit_ivtv_i2c(itv); diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c index 3e1deec..fc8b1ea 100644 --- a/drivers/media/video/ivtv/ivtv-queue.c +++ b/drivers/media/video/ivtv/ivtv-queue.c @@ -203,14 +203,14 @@ int ivtv_stream_alloc(struct ivtv_stream *s) s->dma != PCI_DMA_NONE ? "DMA " : "", s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); - s->sg_pending = kzalloc(SGsize, GFP_KERNEL); + s->sg_pending = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN); if (s->sg_pending == NULL) { IVTV_ERR("Could not allocate sg_pending for %s stream\n", s->name); return -ENOMEM; } s->sg_pending_size = 0; - s->sg_processing = kzalloc(SGsize, GFP_KERNEL); + s->sg_processing = kzalloc(SGsize, GFP_KERNEL|__GFP_NOWARN); if (s->sg_processing == NULL) { IVTV_ERR("Could not allocate sg_processing for %s stream\n", s->name); kfree(s->sg_pending); @@ -219,7 +219,8 @@ int ivtv_stream_alloc(struct ivtv_stream *s) } s->sg_processing_size = 0; - s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element), GFP_KERNEL); + s->sg_dma = kzalloc(sizeof(struct ivtv_sg_element), + GFP_KERNEL|__GFP_NOWARN); if (s->sg_dma == NULL) { IVTV_ERR("Could not allocate sg_dma for %s stream\n", s->name); kfree(s->sg_pending); @@ -235,11 +236,12 @@ int ivtv_stream_alloc(struct ivtv_stream *s) /* allocate stream buffers. Initially all buffers are in q_free. */ for (i = 0; i < s->buffers; i++) { - struct ivtv_buffer *buf = kzalloc(sizeof(struct ivtv_buffer), GFP_KERNEL); + struct ivtv_buffer *buf = kzalloc(sizeof(struct ivtv_buffer), + GFP_KERNEL|__GFP_NOWARN); if (buf == NULL) break; - buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL); + buf->buf = kmalloc(s->buf_size + 256, GFP_KERNEL|__GFP_NOWARN); if (buf->buf == NULL) { kfree(buf); break; diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 4ab8d36..c47c2b9 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -244,7 +244,7 @@ int ivtv_streams_setup(struct ivtv *itv) return 0; /* One or more streams could not be initialized. Clean 'em all up. */ - ivtv_streams_cleanup(itv); + ivtv_streams_cleanup(itv, 0); return -ENOMEM; } @@ -304,12 +304,12 @@ int ivtv_streams_register(struct ivtv *itv) return 0; /* One or more streams could not be initialized. Clean 'em all up. */ - ivtv_streams_cleanup(itv); + ivtv_streams_cleanup(itv, 1); return -ENOMEM; } /* Unregister v4l2 devices */ -void ivtv_streams_cleanup(struct ivtv *itv) +void ivtv_streams_cleanup(struct ivtv *itv, int unregister) { int type; @@ -322,8 +322,11 @@ void ivtv_streams_cleanup(struct ivtv *itv) continue; ivtv_stream_free(&itv->streams[type]); - /* Unregister device */ - video_unregister_device(vdev); + /* Unregister or release device */ + if (unregister) + video_unregister_device(vdev); + else + video_device_release(vdev); } } diff --git a/drivers/media/video/ivtv/ivtv-streams.h b/drivers/media/video/ivtv/ivtv-streams.h index 3d76a41..a653a513 100644 --- a/drivers/media/video/ivtv/ivtv-streams.h +++ b/drivers/media/video/ivtv/ivtv-streams.h @@ -23,7 +23,7 @@ int ivtv_streams_setup(struct ivtv *itv); int ivtv_streams_register(struct ivtv *itv); -void ivtv_streams_cleanup(struct ivtv *itv); +void ivtv_streams_cleanup(struct ivtv *itv, int unregister); /* Capture related */ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s); diff --git a/drivers/media/video/ivtv/ivtv-yuv.c b/drivers/media/video/ivtv/ivtv-yuv.c index 62f70bd..a9417f6 100644 --- a/drivers/media/video/ivtv/ivtv-yuv.c +++ b/drivers/media/video/ivtv/ivtv-yuv.c @@ -908,7 +908,7 @@ static void ivtv_yuv_init(struct ivtv *itv) } /* We need a buffer for blanking when Y plane is offset - non-fatal if we can't get one */ - yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL); + yi->blanking_ptr = kzalloc(720 * 16, GFP_KERNEL|__GFP_NOWARN); if (yi->blanking_ptr) { yi->blanking_dmaptr = pci_map_single(itv->dev, yi->blanking_ptr, 720*16, PCI_DMA_TODEVICE); } else { diff --git a/drivers/media/video/ivtv/ivtvfb.c b/drivers/media/video/ivtv/ivtvfb.c index df789f6..73be154 100644 --- a/drivers/media/video/ivtv/ivtvfb.c +++ b/drivers/media/video/ivtv/ivtvfb.c @@ -948,7 +948,8 @@ static int ivtvfb_init_vidmode(struct ivtv *itv) } /* Allocate the pseudo palette */ - oi->ivtvfb_info.pseudo_palette = kmalloc(sizeof(u32) * 16, GFP_KERNEL); + oi->ivtvfb_info.pseudo_palette = + kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN); if (!oi->ivtvfb_info.pseudo_palette) { IVTVFB_ERR("abort, unable to alloc pseudo pallete\n"); @@ -1056,7 +1057,8 @@ static int ivtvfb_init_card(struct ivtv *itv) return -EBUSY; } - itv->osd_info = kzalloc(sizeof(struct osd_info), GFP_ATOMIC); + itv->osd_info = kzalloc(sizeof(struct osd_info), + GFP_ATOMIC|__GFP_NOWARN); if (itv->osd_info == NULL) { IVTVFB_ERR("Failed to allocate memory for osd_info\n"); return -ENOMEM; -- cgit v1.1 From 50510993e0452e0941fd03f63aa08256dd9c7fdc Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 5 May 2008 18:25:22 -0300 Subject: V4L/DVB (7856): cx18/: possible cleanups This patch contains the following possible cleanups: - cx18-i2c.c should #include "cx18-i2c.h" for getting the prototypes of it's global functions - make the following needlessly global functions static: - cx18-fileops.c:cx18_claim_stream() - cx18-fileops.c:cx18_release_stream() - cx18-queue.c:cx18_queue_move() - remove the following unused functions: - cx18-driver.c:cx18_waitq() - cx18-queue.c:cx18_buf_copy_from_user() Signed-off-by: Adrian Bunk Reviewed-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 10 ---------- drivers/media/video/cx18/cx18-driver.h | 3 --- drivers/media/video/cx18/cx18-fileops.c | 4 ++-- drivers/media/video/cx18/cx18-fileops.h | 9 --------- drivers/media/video/cx18/cx18-i2c.c | 1 + drivers/media/video/cx18/cx18-queue.c | 16 +++------------- drivers/media/video/cx18/cx18-queue.h | 4 ---- 7 files changed, 6 insertions(+), 41 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 9453223..3e9979e 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -164,16 +164,6 @@ MODULE_LICENSE("GPL"); MODULE_VERSION(CX18_VERSION); -int cx18_waitq(wait_queue_head_t *waitq) -{ - DEFINE_WAIT(wait); - - prepare_to_wait(waitq, &wait, TASK_INTERRUPTIBLE); - schedule(); - finish_wait(waitq, &wait); - return signal_pending(current) ? -EINTR : 0; -} - /* Generic utility functions */ int cx18_msleep_timeout(unsigned int msecs, int intr) { diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h index 2ee9391..a2a6c58 100644 --- a/drivers/media/video/cx18/cx18-driver.h +++ b/drivers/media/video/cx18/cx18-driver.h @@ -444,9 +444,6 @@ extern spinlock_t cx18_cards_lock; /* Return non-zero if a signal is pending */ int cx18_msleep_timeout(unsigned int msecs, int intr); -/* Wait on queue, returns -EINTR if interrupted */ -int cx18_waitq(wait_queue_head_t *waitq); - /* Read Hauppauge eeprom */ struct tveeprom; /* forward reference */ void cx18_read_eeprom(struct cx18 *cx, struct tveeprom *tv); diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 6930306..91eff6e 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -39,7 +39,7 @@ associated VBI streams are also automatically claimed. Possible error returns: -EBUSY if someone else has claimed the stream or 0 on success. */ -int cx18_claim_stream(struct cx18_open_id *id, int type) +static int cx18_claim_stream(struct cx18_open_id *id, int type) { struct cx18 *cx = id->cx; struct cx18_stream *s = &cx->streams[type]; @@ -87,7 +87,7 @@ int cx18_claim_stream(struct cx18_open_id *id, int type) /* This function releases a previously claimed stream. It will take into account associated VBI streams. */ -void cx18_release_stream(struct cx18_stream *s) +static void cx18_release_stream(struct cx18_stream *s) { struct cx18 *cx = s->cx; struct cx18_stream *s_vbi; diff --git a/drivers/media/video/cx18/cx18-fileops.h b/drivers/media/video/cx18/cx18-fileops.h index 16cdafb..46da028 100644 --- a/drivers/media/video/cx18/cx18-fileops.h +++ b/drivers/media/video/cx18/cx18-fileops.h @@ -34,12 +34,3 @@ void cx18_stop_capture(struct cx18_open_id *id, int gop_end); void cx18_mute(struct cx18 *cx); void cx18_unmute(struct cx18 *cx); -/* Utilities */ - -/* Try to claim a stream for the filehandle. Return 0 on success, - -EBUSY if stream already claimed. Once a stream is claimed, it - remains claimed until the associated filehandle is closed. */ -int cx18_claim_stream(struct cx18_open_id *id, int type); - -/* Release a previously claimed stream. */ -void cx18_release_stream(struct cx18_stream *s); diff --git a/drivers/media/video/cx18/cx18-i2c.c b/drivers/media/video/cx18/cx18-i2c.c index 18c88d1..4f08a40 100644 --- a/drivers/media/video/cx18/cx18-i2c.c +++ b/drivers/media/video/cx18/cx18-i2c.c @@ -25,6 +25,7 @@ #include "cx18-cards.h" #include "cx18-gpio.h" #include "cx18-av-core.h" +#include "cx18-i2c.h" #include diff --git a/drivers/media/video/cx18/cx18-queue.c b/drivers/media/video/cx18/cx18-queue.c index 4ef6996..6990b77 100644 --- a/drivers/media/video/cx18/cx18-queue.c +++ b/drivers/media/video/cx18/cx18-queue.c @@ -26,17 +26,6 @@ #include "cx18-queue.h" #include "cx18-scb.h" -int cx18_buf_copy_from_user(struct cx18_stream *s, struct cx18_buffer *buf, - const char __user *src, int copybytes) -{ - if (s->buf_size - buf->bytesused < copybytes) - copybytes = s->buf_size - buf->bytesused; - if (copy_from_user(buf->buf + buf->bytesused, src, copybytes)) - return -EFAULT; - buf->bytesused += copybytes; - return copybytes; -} - void cx18_buf_swap(struct cx18_buffer *buf) { int i; @@ -159,8 +148,9 @@ static void cx18_queue_move_buf(struct cx18_stream *s, struct cx18_queue *from, -ENOMEM is returned if the buffers could not be obtained, 0 if all buffers where obtained from the 'from' list and if non-zero then the number of stolen buffers is returned. */ -int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from, - struct cx18_queue *steal, struct cx18_queue *to, int needed_bytes) +static int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from, + struct cx18_queue *steal, struct cx18_queue *to, + int needed_bytes) { unsigned long flags; int rc = 0; diff --git a/drivers/media/video/cx18/cx18-queue.h b/drivers/media/video/cx18/cx18-queue.h index f86c8a6..91423b9 100644 --- a/drivers/media/video/cx18/cx18-queue.h +++ b/drivers/media/video/cx18/cx18-queue.h @@ -39,8 +39,6 @@ static inline void cx18_buf_sync_for_device(struct cx18_stream *s, s->buf_size, s->dma); } -int cx18_buf_copy_from_user(struct cx18_stream *s, struct cx18_buffer *buf, - const char __user *src, int copybytes); void cx18_buf_swap(struct cx18_buffer *buf); /* cx18_queue utility functions */ @@ -48,8 +46,6 @@ void cx18_queue_init(struct cx18_queue *q); void cx18_enqueue(struct cx18_stream *s, struct cx18_buffer *buf, struct cx18_queue *q); struct cx18_buffer *cx18_dequeue(struct cx18_stream *s, struct cx18_queue *q); -int cx18_queue_move(struct cx18_stream *s, struct cx18_queue *from, - struct cx18_queue *steal, struct cx18_queue *to, int needed_bytes); struct cx18_buffer *cx18_queue_find_buf(struct cx18_stream *s, u32 id, u32 bytesused); void cx18_flush_queues(struct cx18_stream *s); -- cgit v1.1 From 4ed83b51d3669628d970c2fea604064d2e0ac6af Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 28 Apr 2008 15:39:09 -0300 Subject: V4L/DVB (7857): make itd1000_fre_values[] static const itd1000_fre_values[] can become static const. Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/itd1000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/itd1000.c b/drivers/media/dvb/frontends/itd1000.c index 04c562c..600dad6 100644 --- a/drivers/media/dvb/frontends/itd1000.c +++ b/drivers/media/dvb/frontends/itd1000.c @@ -195,7 +195,7 @@ static void itd1000_set_vco(struct itd1000_state *state, u32 freq_khz) } } -struct { +static const struct { u32 freq; u8 values[10]; /* RFTR, RFST1 - RFST9 */ } itd1000_fre_values[] = { -- cgit v1.1 From 91e64c884295c7347f9ea78347d5a5e2df2441f6 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 5 May 2008 13:57:50 -0300 Subject: V4L/DVB (7858): video: build fix for drivers/media/video/mt9v022.c x86.git testing found the following build bug on latest -git: CC [M] drivers/media/video/mt9v022.o drivers/media/video/mt9v022.c: In function 'bus_switch_request': drivers/media/video/mt9v022.c:199: error: implicit declaration of function 'gpio_is_valid' drivers/media/video/mt9v022.c:201: error: implicit declaration of function 'gpio_request' drivers/media/video/mt9v022.c:207: error: implicit declaration of function 'gpio_direction_output' drivers/media/video/mt9v022.c:211: error: implicit declaration of function 'gpio_free' drivers/media/video/mt9v022.c: In function 'bus_switch_act': drivers/media/video/mt9v022.c:237: error: implicit declaration of function 'gpio_set_value_cansleep' make[2]: *** [drivers/media/video] Error 2 make[1]: *** [drivers/media] Error 2 make[1]: *** Waiting for unfinished jobs.... make: *** [drivers] Error 2 with this config: http://redhat.com/~mingo/misc/config-Sat_May__3_16_08_39_CEST_2008.bad the bug was that the driver uses GPIO functionality but only includes the GPIO interface definitions for the CONFIG_MT9M001_PCA9536_SWITCH case, which was not set in this config. The quick fix seems to be to include linux/gpio.h unconditionally. (this seems like a small cleanup as well as it removes and #ifdef is more robust than an inclusion of asm/gpio.h) Not tested too much yet, so please have another look in any case. Signed-off-by: Ingo Molnar Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9m001.c | 5 +---- drivers/media/video/mt9v022.c | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index 179e470..ee43499 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -12,15 +12,12 @@ #include #include #include +#include #include #include #include -#ifdef CONFIG_MT9M001_PCA9536_SWITCH -#include -#endif - /* mt9m001 i2c address 0x5d * The platform has to define i2c_board_info * and call i2c_register_board_info() */ diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index d1391ac..80f7668 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -13,15 +13,12 @@ #include #include #include +#include #include #include #include -#ifdef CONFIG_MT9M001_PCA9536_SWITCH -#include -#endif - /* mt9v022 i2c address 0x48, 0x4c, 0x58, 0x5c * The platform has to define i2c_board_info * and call i2c_register_board_info() */ -- cgit v1.1 From 7fb0fd05b2f03065ca4743e8c7446ec86329c4c8 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 5 May 2008 14:12:30 -0300 Subject: V4L/DVB (7859): mt9v022: fix a copy-paste error in comment Signed-off-by: Guennadi Liakhovetski Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/mt9v022.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index 80f7668..1658fe5 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -88,7 +88,7 @@ static const struct soc_camera_data_format mt9v022_monochrome_formats[] = { struct mt9v022 { struct i2c_client *client; struct soc_camera_device icd; - int model; /* V4L2_IDENT_MT9M001* codes from v4l2-chip-ident.h */ + int model; /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */ int switch_gpio; u16 chip_control; unsigned char datawidth; -- cgit v1.1 From 6d8425b1e38f69e349818299f245d35fb5c3a7d5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 5 May 2008 18:25:22 -0300 Subject: V4L/DVB (7860a): Add MAINTAINERS for cx18 Signed-off-by: Hans Verkuil Signed-off-by: Andy Walls Signed-off-by: Mauro Carvalho Chehab --- MAINTAINERS | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index b18242f..bc1c008 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1230,6 +1230,15 @@ P: Jaya Kumar M: jayakumar.alsa@gmail.com S: Maintained +CX18 VIDEO4LINUX DRIVER +P: Hans Verkuil, Andy Walls +M: hverkuil@xs4all.nl, awalls@radix.net +L: ivtv-devel@ivtvdriver.org +L: ivtv-users@ivtvdriver.org +L: video4linux-list@redhat.com +W: http://linuxtv.org +S: Maintained + CYBERPRO FB DRIVER P: Russell King M: rmk@arm.linux.org.uk -- cgit v1.1 From e4671b6bc0b5b488adc5acbcfcbfa6661abec94e Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Wed, 30 Apr 2008 12:21:04 -0300 Subject: V4L/DVB (7861): mt312: Prefix functions only with mt312_, Add zl10313 to kconfig description This patch does some small cleanup to mt312. It changes kconfig description to also list the ZL10313. It does change some strange symbol names to be consistent with module name mt312 and naming of all other functions in there. * vp310_mt312_ops -> mt312_ops * vp310_mt312_attach -> mt312_attach Adds a MODULE_AUTHOR for me Signed-off-by: Matthias Schwarzott Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/b2c2/flexcop-fe-tuner.c | 2 +- drivers/media/dvb/frontends/Kconfig | 2 +- drivers/media/dvb/frontends/mt312.c | 9 +++++---- drivers/media/dvb/frontends/mt312.h | 4 ++-- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c index 7b0ea3b..f9d0876 100644 --- a/drivers/media/dvb/b2c2/flexcop-fe-tuner.c +++ b/drivers/media/dvb/b2c2/flexcop-fe-tuner.c @@ -634,7 +634,7 @@ int flexcop_frontend_init(struct flexcop_device *fc) } /* try the sky v2.3 (vp310/Samsung tbdu18132(tsa5059)) */ - fc->fe = dvb_attach(vp310_mt312_attach, + fc->fe = dvb_attach(mt312_attach, &skystar23_samsung_tbdu18132_config, i2c); if (fc->fe != NULL) { ops = &fc->fe->ops; diff --git a/drivers/media/dvb/frontends/Kconfig b/drivers/media/dvb/frontends/Kconfig index 47d0215..c20553c 100644 --- a/drivers/media/dvb/frontends/Kconfig +++ b/drivers/media/dvb/frontends/Kconfig @@ -30,7 +30,7 @@ config DVB_CX24123 A DVB-S tuner module. Say Y when you want to support this frontend. config DVB_MT312 - tristate "Zarlink VP310/MT312 based" + tristate "Zarlink VP310/MT312/ZL10313 based" depends on DVB_CORE && I2C default m if DVB_FE_CUSTOMISE help diff --git a/drivers/media/dvb/frontends/mt312.c b/drivers/media/dvb/frontends/mt312.c index 081ca33..5ac9b15 100644 --- a/drivers/media/dvb/frontends/mt312.c +++ b/drivers/media/dvb/frontends/mt312.c @@ -737,7 +737,7 @@ static void mt312_release(struct dvb_frontend *fe) } #define MT312_SYS_CLK 90000000UL /* 90 MHz */ -static struct dvb_frontend_ops vp310_mt312_ops = { +static struct dvb_frontend_ops mt312_ops = { .info = { .name = "Zarlink ???? DVB-S", @@ -776,7 +776,7 @@ static struct dvb_frontend_ops vp310_mt312_ops = { .set_voltage = mt312_set_voltage, }; -struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config, +struct dvb_frontend *mt312_attach(const struct mt312_config *config, struct i2c_adapter *i2c) { struct mt312_state *state = NULL; @@ -795,7 +795,7 @@ struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config, goto error; /* create dvb_frontend */ - memcpy(&state->frontend.ops, &vp310_mt312_ops, + memcpy(&state->frontend.ops, &mt312_ops, sizeof(struct dvb_frontend_ops)); state->frontend.demodulator_priv = state; @@ -827,12 +827,13 @@ error: kfree(state); return NULL; } -EXPORT_SYMBOL(vp310_mt312_attach); +EXPORT_SYMBOL(mt312_attach); module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); MODULE_DESCRIPTION("Zarlink VP310/MT312/ZL10313 DVB-S Demodulator driver"); MODULE_AUTHOR("Andreas Oberritter "); +MODULE_AUTHOR("Matthias Schwarzott "); MODULE_LICENSE("GPL"); diff --git a/drivers/media/dvb/frontends/mt312.h b/drivers/media/dvb/frontends/mt312.h index de796ea..29e3bb5 100644 --- a/drivers/media/dvb/frontends/mt312.h +++ b/drivers/media/dvb/frontends/mt312.h @@ -37,10 +37,10 @@ struct mt312_config { }; #if defined(CONFIG_DVB_MT312) || (defined(CONFIG_DVB_MT312_MODULE) && defined(MODULE)) -struct dvb_frontend *vp310_mt312_attach(const struct mt312_config *config, +struct dvb_frontend *mt312_attach(const struct mt312_config *config, struct i2c_adapter *i2c); #else -static inline struct dvb_frontend *vp310_mt312_attach( +static inline struct dvb_frontend *mt312_attach( const struct mt312_config *config, struct i2c_adapter *i2c) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); -- cgit v1.1 From 52c99bda04d8bb1fb390821695b0f9efc1e1db44 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 1 May 2008 04:57:01 -0300 Subject: V4L/DVB (7862): Add mxl5505s driver for MaxiLinear 5505 chipsets Initial check-in of the original driver to establish history. Signed-off-by: Chia-Ling Lu Developer Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 4989 ++++++++++++++++++++++++++++++++ drivers/media/common/tuners/mxl5005s.h | 718 +++++ 2 files changed, 5707 insertions(+) create mode 100644 drivers/media/common/tuners/mxl5005s.c create mode 100644 drivers/media/common/tuners/mxl5005s.h diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c new file mode 100644 index 0000000..a32475f --- /dev/null +++ b/drivers/media/common/tuners/mxl5005s.c @@ -0,0 +1,4989 @@ +/* + * For the Realtek RTL chip RTL2831U + * Realtek Release Date: 2008-03-14, ver 080314 + * Realtek version RTL2831 Linux driver version 080314 + * ver 080314 + * + * for linux kernel version 2.6.21.4 - 2.6.22-14 + * support MXL5005s and MT2060 tuners (support tuner auto-detecting) + * support two IR types -- RC5 and NEC + * + * Known boards with Realtek RTL chip RTL2821U + * Freecom USB stick 14aa:0160 (version 4) + * Conceptronic CTVDIGRCU + * + * Copyright (c) 2008 Realtek + * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper + * This code is placed under the terms of the GNU General Public License + * + * Released by Realtek under GPLv2. + * Thanks to Realtek for a lot of support we received ! + * + * Revision: 080314 - original version + */ + + +/** + +@file + +@brief MxL5005S tuner module definition + +One can manipulate MxL5005S tuner through MxL5005S module. +MxL5005S module is derived from tuner module. + +*/ + + +#include "tuner_mxl5005s.h" +#include "tuner_demod_io.h" + + + + + + +/** + +@defgroup MXL5005S_TUNER_MODULE MxL5005S tuner module + +MxL5005S tuner module is drived from tuner base module. + +@see TUNER_BASE_MODULE + +*/ + + + + + +/** + +@defgroup MXL5005S_MODULE_BUILDER MxL5005S module builder +@ingroup MXL5005S_TUNER_MODULE + +One should call MxL5005S module builder before using MxL5005S module. + +*/ +/// @{ + + + + + +/** + +@brief MxL5005S tuner module builder + +Use BuildMxl5005sModule() to build MxL5005S module, set all module function pointers with the corresponding functions, +and initialize module private variables. + + +@param [in] ppTuner Pointer to MxL5005S tuner module pointer +@param [in] pTunerModuleMemory Pointer to an allocated tuner module memory +@param [in] pMxl5005sExtraModuleMemory Pointer to an allocated MxL5005S extra module memory +@param [in] pI2cBridgeModuleMemory Pointer to an allocated I2C bridge module memory +@param [in] DeviceAddr MxL5005S I2C device address +@param [in] CrystalFreqHz MxL5005S crystal frequency in Hz + + +@note \n + -# One should call BuildMxl5005sModule() to build MxL5005S module before using it. + +*/ +void +BuildMxl5005sModule( + TUNER_MODULE **ppTuner, + TUNER_MODULE *pTunerModuleMemory, + MXL5005S_EXTRA_MODULE *pMxl5005sExtraModuleMemory, + BASE_INTERFACE_MODULE *pBaseInterfaceModuleMemory, + I2C_BRIDGE_MODULE *pI2cBridgeModuleMemory, + unsigned char DeviceAddr, + int StandardMode + ) +{ + MXL5005S_EXTRA_MODULE *pExtra; + + int MxlModMode; + int MxlIfMode; + unsigned long MxlBandwitdh; + unsigned long MxlIfFreqHz; + unsigned long MxlCrystalFreqHz; + int MxlAgcMode; + unsigned short MxlTop; + unsigned short MxlIfOutputLoad; + int MxlClockOut; + int MxlDivOut; + int MxlCapSel; + int MxlRssiOnOff; + unsigned char MxlStandard; + unsigned char MxlTfType; + + + + // Set tuner module pointer, tuner extra module pointer, and I2C bridge module pointer. + *ppTuner = pTunerModuleMemory; + (*ppTuner)->pExtra = pMxl5005sExtraModuleMemory; + (*ppTuner)->pBaseInterface = pBaseInterfaceModuleMemory; + (*ppTuner)->pI2cBridge = pI2cBridgeModuleMemory; + + // Get tuner extra module pointer. + pExtra = (MXL5005S_EXTRA_MODULE *)(*ppTuner)->pExtra; + + + // Set I2C bridge tuner arguments. + mxl5005s_SetI2cBridgeModuleTunerArg(*ppTuner); + + + // Set tuner module manipulating function pointers. + (*ppTuner)->SetDeviceAddr = mxl5005s_SetDeviceAddr; + + (*ppTuner)->GetTunerType = mxl5005s_GetTunerType; + (*ppTuner)->GetDeviceAddr = mxl5005s_GetDeviceAddr; + + (*ppTuner)->Initialize = mxl5005s_Initialize; + (*ppTuner)->SetRfFreqHz = mxl5005s_SetRfFreqHz; + (*ppTuner)->GetRfFreqHz = mxl5005s_GetRfFreqHz; + + + // Set tuner extra module manipulating function pointers. + pExtra->SetRegsWithTable = mxl5005s_SetRegsWithTable; + pExtra->SetRegMaskBits = mxl5005s_SetRegMaskBits; + pExtra->SetSpectrumMode = mxl5005s_SetSpectrumMode; + pExtra->SetBandwidthHz = mxl5005s_SetBandwidthHz; + + + // Initialize tuner parameter setting status. + (*ppTuner)->IsDeviceAddrSet = NO; + (*ppTuner)->IsRfFreqHzSet = NO; + + + // Set MxL5005S parameters. + MxlModMode = MXL_DIGITAL_MODE; + MxlIfMode = MXL_ZERO_IF; + MxlBandwitdh = MXL5005S_BANDWIDTH_8MHZ; + MxlIfFreqHz = IF_FREQ_4570000HZ; + MxlCrystalFreqHz = CRYSTAL_FREQ_16000000HZ; + MxlAgcMode = MXL_SINGLE_AGC; + MxlTop = MXL5005S_TOP_25P2; + MxlIfOutputLoad = MXL5005S_IF_OUTPUT_LOAD_200_OHM; + MxlClockOut = MXL_CLOCK_OUT_DISABLE; + MxlDivOut = MXL_DIV_OUT_4; + MxlCapSel = MXL_CAP_SEL_ENABLE; + MxlRssiOnOff = MXL_RSSI_ENABLE; + MxlTfType = MXL_TF_C_H; + + + // Set MxL5005S parameters according to standard mode + switch(StandardMode) + { + default: + case MXL5005S_STANDARD_DVBT: MxlStandard = MXL_DVBT; break; + case MXL5005S_STANDARD_ATSC: MxlStandard = MXL_ATSC; break; + } + + + // Set MxL5005S extra module. + pExtra->AgcMasterByte = (MxlAgcMode == MXL_DUAL_AGC) ? 0x4 : 0x0; + + MXL5005_TunerConfig(&pExtra->MxlDefinedTunerStructure, (unsigned char)MxlModMode, (unsigned char)MxlIfMode, + MxlBandwitdh, MxlIfFreqHz, MxlCrystalFreqHz, (unsigned char)MxlAgcMode, MxlTop, MxlIfOutputLoad, + (unsigned char)MxlClockOut, (unsigned char)MxlDivOut, (unsigned char)MxlCapSel, (unsigned char)MxlRssiOnOff, + MxlStandard, MxlTfType); + + + + // Note: Need to set all module arguments before using module functions. + + + // Set tuner type. + (*ppTuner)->TunerType = TUNER_TYPE_MXL5005S; + + // Set tuner I2C device address. + (*ppTuner)->SetDeviceAddr(*ppTuner, DeviceAddr); + + + return; +} + + + + + +/// @} + + + + + +/** + +@defgroup MXL5005S_MANIPULATING_FUNCTIONS MxL5005S manipulating functions derived from tuner base module +@ingroup MXL5005S_TUNER_MODULE + +One can use the MxL5005S tuner module manipulating interface implemented by MxL5005S manipulating functions to +manipulate MxL5005S tuner. + +*/ +/// @{ + + + + + +/** + +@brief Set MxL5005S tuner I2C device address. + +@note \n + -# MxL5005S tuner builder will set TUNER_FP_SET_DEVICE_ADDR() function pointer with mxl5005s_SetDeviceAddr(). + +@see TUNER_FP_SET_DEVICE_ADDR + +*/ +void +mxl5005s_SetDeviceAddr( + TUNER_MODULE *pTuner, + unsigned char DeviceAddr + ) +{ + // Set tuner I2C device address. + pTuner->DeviceAddr = DeviceAddr; + pTuner->IsDeviceAddrSet = YES; + + + return; +} + + + + + +/** + +@brief Get MxL5005S tuner type. + +@note \n + -# MxL5005S tuner builder will set TUNER_FP_GET_TUNER_TYPE() function pointer with mxl5005s_GetTunerType(). + +@see TUNER_FP_GET_TUNER_TYPE + +*/ +void +mxl5005s_GetTunerType( + TUNER_MODULE *pTuner, + int *pTunerType + ) +{ + // Get tuner type from tuner module. + *pTunerType = pTuner->TunerType; + + + return; +} + + + + + +/** + +@brief Get MxL5005S tuner I2C device address. + +@note \n + -# MxL5005S tuner builder will set TUNER_FP_GET_DEVICE_ADDR() function pointer with mxl5005s_GetDeviceAddr(). + +@see TUNER_FP_GET_DEVICE_ADDR + +*/ +int +mxl5005s_GetDeviceAddr( + TUNER_MODULE *pTuner, + unsigned char *pDeviceAddr + ) +{ + // Get tuner I2C device address from tuner module. + if(pTuner->IsDeviceAddrSet != YES) + goto error_status_get_tuner_i2c_device_addr; + + *pDeviceAddr = pTuner->DeviceAddr; + + + return FUNCTION_SUCCESS; + + +error_status_get_tuner_i2c_device_addr: + return FUNCTION_ERROR; +} + + + + + +/** + +@brief Initialize MxL5005S tuner. + +@note \n + -# MxL5005S tuner builder will set TUNER_FP_INITIALIZE() function pointer with mxl5005s_Initialize(). + +@see TUNER_FP_INITIALIZE + +*/ +int +mxl5005s_Initialize( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner + ) +{ + MXL5005S_EXTRA_MODULE *pExtra; + + unsigned char AgcMasterByte; + unsigned char AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; + unsigned char ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; + int TableLen; + + + + // Get tuner extra module. + pExtra = (MXL5005S_EXTRA_MODULE *)pTuner->pExtra; + + + // Get AGC master byte + AgcMasterByte = pExtra->AgcMasterByte; + + + // Initialize MxL5005S tuner according to MxL5005S tuner example code. + + // Tuner initialization stage 0 + MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET); + AddrTable[0] = MASTER_CONTROL_ADDR; + ByteTable[0] |= AgcMasterByte; + + if(pExtra->SetRegsWithTable( dib,pTuner, AddrTable, ByteTable, LEN_1_BYTE) != FUNCTION_SUCCESS) + goto error_status_set_tuner_registers; + + + // Tuner initialization stage 1 + MXL_GetInitRegister(&pExtra->MxlDefinedTunerStructure, AddrTable, ByteTable, &TableLen); + + if(pExtra->SetRegsWithTable( dib,pTuner, AddrTable, ByteTable, TableLen) != FUNCTION_SUCCESS) + goto error_status_set_tuner_registers; + + + return FUNCTION_SUCCESS; + + +error_status_set_tuner_registers: + return FUNCTION_ERROR; +} + + + + + +/** + +@brief Set MxL5005S tuner RF frequency in Hz. + +@note \n + -# MxL5005S tuner builder will set TUNER_FP_SET_RF_FREQ_HZ() function pointer with mxl5005s_SetRfFreqHz(). + +@see TUNER_FP_SET_RF_FREQ_HZ + +*/ +int +mxl5005s_SetRfFreqHz( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + unsigned long RfFreqHz + ) +{ + MXL5005S_EXTRA_MODULE *pExtra; + BASE_INTERFACE_MODULE *pBaseInterface; + + unsigned char AgcMasterByte; + unsigned char AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; + unsigned char ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; + int TableLen; + + unsigned long IfDivval; + unsigned char MasterControlByte; + + + + // Get tuner extra module and base interface module. + pExtra = (MXL5005S_EXTRA_MODULE *)pTuner->pExtra; + pBaseInterface = pTuner->pBaseInterface; + + + // Get AGC master byte + AgcMasterByte = pExtra->AgcMasterByte; + + + // Set MxL5005S tuner RF frequency according to MxL5005S tuner example code. + + // Tuner RF frequency setting stage 0 + MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET) ; + AddrTable[0] = MASTER_CONTROL_ADDR; + ByteTable[0] |= AgcMasterByte; + + if(pExtra->SetRegsWithTable( dib,pTuner, AddrTable, ByteTable, LEN_1_BYTE) != FUNCTION_SUCCESS) + goto error_status_set_tuner_registers; + + + // Tuner RF frequency setting stage 1 + MXL_TuneRF(&pExtra->MxlDefinedTunerStructure, RfFreqHz); + + MXL_ControlRead(&pExtra->MxlDefinedTunerStructure, IF_DIVVAL, &IfDivval); + + MXL_ControlWrite(&pExtra->MxlDefinedTunerStructure, SEQ_FSM_PULSE, 0); + MXL_ControlWrite(&pExtra->MxlDefinedTunerStructure, SEQ_EXTPOWERUP, 1); + MXL_ControlWrite(&pExtra->MxlDefinedTunerStructure, IF_DIVVAL, 8); + + MXL_GetCHRegister(&pExtra->MxlDefinedTunerStructure, AddrTable, ByteTable, &TableLen) ; + + MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ; + AddrTable[TableLen] = MASTER_CONTROL_ADDR ; + ByteTable[TableLen] = MasterControlByte | AgcMasterByte; + TableLen += 1; + + if(pExtra->SetRegsWithTable( dib,pTuner, AddrTable, ByteTable, TableLen) != FUNCTION_SUCCESS) + goto error_status_set_tuner_registers; + + + // Wait 30 ms. + pBaseInterface->WaitMs(pBaseInterface, 30); + + + // Tuner RF frequency setting stage 2 + MXL_ControlWrite(&pExtra->MxlDefinedTunerStructure, SEQ_FSM_PULSE, 1) ; + MXL_ControlWrite(&pExtra->MxlDefinedTunerStructure, IF_DIVVAL, IfDivval) ; + MXL_GetCHRegister_ZeroIF(&pExtra->MxlDefinedTunerStructure, AddrTable, ByteTable, &TableLen) ; + + MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ; + AddrTable[TableLen] = MASTER_CONTROL_ADDR ; + ByteTable[TableLen] = MasterControlByte | AgcMasterByte ; + TableLen += 1; + + if(pExtra->SetRegsWithTable( dib,pTuner, AddrTable, ByteTable, TableLen) != FUNCTION_SUCCESS) + goto error_status_set_tuner_registers; + + + // Set tuner RF frequency parameter. + pTuner->RfFreqHz = RfFreqHz; + pTuner->IsRfFreqHzSet = YES; + + + return FUNCTION_SUCCESS; + + +error_status_set_tuner_registers: + return FUNCTION_ERROR; +} + + + + + +/** + +@brief Get MxL5005S tuner RF frequency in Hz. + +@note \n + -# MxL5005S tuner builder will set TUNER_FP_GET_RF_FREQ_HZ() function pointer with mxl5005s_GetRfFreqHz(). + +@see TUNER_FP_GET_RF_FREQ_HZ + +*/ +int +mxl5005s_GetRfFreqHz( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + unsigned long *pRfFreqHz + ) +{ + // Get tuner RF frequency in Hz from tuner module. + if(pTuner->IsRfFreqHzSet != YES) + goto error_status_get_tuner_rf_frequency; + + *pRfFreqHz = pTuner->RfFreqHz; + + + return FUNCTION_SUCCESS; + + +error_status_get_tuner_rf_frequency: + return FUNCTION_ERROR; +} + + + + + +/** + +@brief Set MxL5005S tuner registers with table. + +*/ +/* +int +mxl5005s_SetRegsWithTable( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + unsigned char *pAddrTable, + unsigned char *pByteTable, + int TableLen + ) +{ + BASE_INTERFACE_MODULE *pBaseInterface; + I2C_BRIDGE_MODULE *pI2cBridge; + unsigned char WritingByteNumMax; + + int i; + unsigned char WritingBuffer[I2C_BUFFER_LEN]; + unsigned char WritingIndex; + + + + // Get base interface, I2C bridge, and maximum writing byte number. + pBaseInterface = pTuner->pBaseInterface; + pI2cBridge = pTuner->pI2cBridge; + WritingByteNumMax = pBaseInterface->I2cWritingByteNumMax; + + + // Set registers with table. + // Note: 1. The I2C format of MxL5005S is described as follows: + // start_bit + (device_addr | writing_bit) + (register_addr + writing_byte) * n + stop_bit + // ... + // start_bit + (device_addr | writing_bit) + (register_addr + writing_byte) * m + latch_byte + stop_bit + // 2. The latch_byte is 0xfe. + // 3. The following writing byte separating scheme takes latch_byte as two byte data. + for(i = 0, WritingIndex = 0; i < TableLen; i++) + { + // Put register address and register byte value into writing buffer. + WritingBuffer[WritingIndex] = pAddrTable[i]; + WritingBuffer[WritingIndex + 1] = pByteTable[i]; + WritingIndex += 2; + + // If writing buffer is full, send the I2C writing command with writing buffer. + if(WritingIndex > (WritingByteNumMax - 2)) + { + if(pI2cBridge->ForwardI2cWritingCmd(pI2cBridge, WritingBuffer, WritingIndex) != FUNCTION_SUCCESS) + goto error_status_set_tuner_registers; + + WritingIndex = 0; + } + } + + + // Send the last I2C writing command with writing buffer and latch byte. + WritingBuffer[WritingIndex] = MXL5005S_LATCH_BYTE; + WritingIndex += 1; + + if(pI2cBridge->ForwardI2cWritingCmd(pI2cBridge, WritingBuffer, WritingIndex) != FUNCTION_SUCCESS) + goto error_status_set_tuner_registers; + + + return FUNCTION_SUCCESS; + + +error_status_set_tuner_registers: + return FUNCTION_ERROR; +} +*/ + + +int +mxl5005s_SetRegsWithTable( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + unsigned char *pAddrTable, + unsigned char *pByteTable, + int TableLen + ) +{ + int i; + u8 end_two_bytes_buf[]={ 0 , 0 }; + u8 tuner_addr=0x00; + + pTuner->GetDeviceAddr(pTuner , &tuner_addr); + + for( i = 0 ; i < TableLen - 1 ; i++) + { + if ( TUNER_WI2C(dib , tuner_addr , pAddrTable[i] , &pByteTable[i] , 1 ) ) + return FUNCTION_ERROR; + } + + end_two_bytes_buf[0] = pByteTable[i]; + end_two_bytes_buf[1] = MXL5005S_LATCH_BYTE; + + if ( TUNER_WI2C(dib , tuner_addr , pAddrTable[i] , end_two_bytes_buf , 2 ) ) + return FUNCTION_ERROR; + + return FUNCTION_SUCCESS; +} + + + + + +/** + +@brief Set MxL5005S tuner register bits. + +*/ +int +mxl5005s_SetRegMaskBits( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + unsigned char RegAddr, + unsigned char Msb, + unsigned char Lsb, + const unsigned char WritingValue + ) +{ + MXL5005S_EXTRA_MODULE *pExtra; + + int i; + + unsigned char Mask; + unsigned char Shift; + + unsigned char RegByte; + + + + // Get tuner extra module. + pExtra = (MXL5005S_EXTRA_MODULE *)pTuner->pExtra; + + + // Generate mask and shift according to MSB and LSB. + Mask = 0; + for(i = Lsb; i < (unsigned char)(Msb + 1); i++) + Mask |= 0x1 << i; + + Shift = Lsb; + + + // Get tuner register byte according to register adddress. + MXL_RegRead(&pExtra->MxlDefinedTunerStructure, RegAddr, &RegByte); + + + // Reserve register byte unmask bit with mask and inlay writing value into it. + RegByte &= ~Mask; + RegByte |= (WritingValue << Shift) & Mask; + + + // Update tuner register byte table. + MXL_RegWrite(&pExtra->MxlDefinedTunerStructure, RegAddr, RegByte); + + + // Write tuner register byte with writing byte. + if(pExtra->SetRegsWithTable( dib, pTuner, &RegAddr, &RegByte, LEN_1_BYTE) != FUNCTION_SUCCESS) + goto error_status_set_tuner_registers; + + + return FUNCTION_SUCCESS; + + +error_status_set_tuner_registers: + return FUNCTION_ERROR; +} + + + + + +/** + +@brief Set MxL5005S tuner spectrum mode. + +*/ +int +mxl5005s_SetSpectrumMode( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + int SpectrumMode + ) +{ + static const unsigned char BbIqswapTable[SPECTRUM_MODE_NUM] = + { + // BB_IQSWAP + 0, // Normal spectrum + 1, // Inverse spectrum + }; + + + MXL5005S_EXTRA_MODULE *pExtra; + + + + // Get tuner extra module. + pExtra = (MXL5005S_EXTRA_MODULE *)pTuner->pExtra; + + + // Set BB_IQSWAP according to BB_IQSWAP table and spectrum mode. + if(pExtra->SetRegMaskBits(dib,pTuner, MXL5005S_BB_IQSWAP_ADDR, MXL5005S_BB_IQSWAP_MSB, + MXL5005S_BB_IQSWAP_LSB, BbIqswapTable[SpectrumMode]) != FUNCTION_SUCCESS) + goto error_status_set_tuner_registers; + + + return FUNCTION_SUCCESS; + + +error_status_set_tuner_registers: + return FUNCTION_ERROR; +} + + + + + +/** + +@brief Set MxL5005S tuner bandwidth in Hz. + +*/ +int +mxl5005s_SetBandwidthHz( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + unsigned long BandwidthHz + ) +{ + MXL5005S_EXTRA_MODULE *pExtra; + + unsigned char BbDlpfBandsel; + + + + // Get tuner extra module. + pExtra = (MXL5005S_EXTRA_MODULE *)pTuner->pExtra; + + + // Set BB_DLPF_BANDSEL according to bandwidth. + switch(BandwidthHz) + { + default: + case MXL5005S_BANDWIDTH_6MHZ: BbDlpfBandsel = 3; break; + case MXL5005S_BANDWIDTH_7MHZ: BbDlpfBandsel = 2; break; + case MXL5005S_BANDWIDTH_8MHZ: BbDlpfBandsel = 0; break; + } + + if(pExtra->SetRegMaskBits(dib,pTuner, MXL5005S_BB_DLPF_BANDSEL_ADDR, MXL5005S_BB_DLPF_BANDSEL_MSB, + MXL5005S_BB_DLPF_BANDSEL_LSB, BbDlpfBandsel) != FUNCTION_SUCCESS) + goto error_status_set_tuner_registers; + + + return FUNCTION_SUCCESS; + + +error_status_set_tuner_registers: + return FUNCTION_ERROR; +} + + + + + +/// @} + + + + + +/** + +@defgroup MXL5005S_DEPENDENCE MxL5005S dependence +@ingroup MXL5005S_TUNER_MODULE + +MxL5005S dependence is the related functions for MxL5005S tuner module interface. +One should not use MxL5005S dependence directly. + +*/ +/// @{ + + + + + +/** + +@brief Set I2C bridge module tuner arguments. + +MxL5005S builder will use mxl5005s_SetI2cBridgeModuleTunerArg() to set I2C bridge module tuner arguments. + + +@param [in] pTuner The tuner module pointer + + +@see BuildMxl5005sModule() + +*/ +void +mxl5005s_SetI2cBridgeModuleTunerArg( + TUNER_MODULE *pTuner + ) +{ + I2C_BRIDGE_MODULE *pI2cBridge; + + + + // Get I2C bridge module. + pI2cBridge = pTuner->pI2cBridge; + + // Set I2C bridge module tuner arguments. + pI2cBridge->pTunerDeviceAddr = &pTuner->DeviceAddr; + + + return; +} + + + + + +/// @} + + + + + + + + + + + + + + + + + + + + + + + +// The following context is source code provided by MaxLinear. + + + + + +// MaxLinear source code - MXL5005_Initialize.cpp + + + +//#ifdef _MXL_HEADER +//#include "stdafx.h" +//#endif +//#include "MXL5005_c.h" + +_u16 MXL5005_RegisterInit (Tuner_struct * Tuner) +{ + Tuner->TunerRegs_Num = TUNER_REGS_NUM ; +// Tuner->TunerRegs = (TunerReg_struct *) calloc( TUNER_REGS_NUM, sizeof(TunerReg_struct) ) ; + + Tuner->TunerRegs[0].Reg_Num = 9 ; + Tuner->TunerRegs[0].Reg_Val = 0x40 ; + + Tuner->TunerRegs[1].Reg_Num = 11 ; + Tuner->TunerRegs[1].Reg_Val = 0x19 ; + + Tuner->TunerRegs[2].Reg_Num = 12 ; + Tuner->TunerRegs[2].Reg_Val = 0x60 ; + + Tuner->TunerRegs[3].Reg_Num = 13 ; + Tuner->TunerRegs[3].Reg_Val = 0x00 ; + + Tuner->TunerRegs[4].Reg_Num = 14 ; + Tuner->TunerRegs[4].Reg_Val = 0x00 ; + + Tuner->TunerRegs[5].Reg_Num = 15 ; + Tuner->TunerRegs[5].Reg_Val = 0xC0 ; + + Tuner->TunerRegs[6].Reg_Num = 16 ; + Tuner->TunerRegs[6].Reg_Val = 0x00 ; + + Tuner->TunerRegs[7].Reg_Num = 17 ; + Tuner->TunerRegs[7].Reg_Val = 0x00 ; + + Tuner->TunerRegs[8].Reg_Num = 18 ; + Tuner->TunerRegs[8].Reg_Val = 0x00 ; + + Tuner->TunerRegs[9].Reg_Num = 19 ; + Tuner->TunerRegs[9].Reg_Val = 0x34 ; + + Tuner->TunerRegs[10].Reg_Num = 21 ; + Tuner->TunerRegs[10].Reg_Val = 0x00 ; + + Tuner->TunerRegs[11].Reg_Num = 22 ; + Tuner->TunerRegs[11].Reg_Val = 0x6B ; + + Tuner->TunerRegs[12].Reg_Num = 23 ; + Tuner->TunerRegs[12].Reg_Val = 0x35 ; + + Tuner->TunerRegs[13].Reg_Num = 24 ; + Tuner->TunerRegs[13].Reg_Val = 0x70 ; + + Tuner->TunerRegs[14].Reg_Num = 25 ; + Tuner->TunerRegs[14].Reg_Val = 0x3E ; + + Tuner->TunerRegs[15].Reg_Num = 26 ; + Tuner->TunerRegs[15].Reg_Val = 0x82 ; + + Tuner->TunerRegs[16].Reg_Num = 31 ; + Tuner->TunerRegs[16].Reg_Val = 0x00 ; + + Tuner->TunerRegs[17].Reg_Num = 32 ; + Tuner->TunerRegs[17].Reg_Val = 0x40 ; + + Tuner->TunerRegs[18].Reg_Num = 33 ; + Tuner->TunerRegs[18].Reg_Val = 0x53 ; + + Tuner->TunerRegs[19].Reg_Num = 34 ; + Tuner->TunerRegs[19].Reg_Val = 0x81 ; + + Tuner->TunerRegs[20].Reg_Num = 35 ; + Tuner->TunerRegs[20].Reg_Val = 0xC9 ; + + Tuner->TunerRegs[21].Reg_Num = 36 ; + Tuner->TunerRegs[21].Reg_Val = 0x01 ; + + Tuner->TunerRegs[22].Reg_Num = 37 ; + Tuner->TunerRegs[22].Reg_Val = 0x00 ; + + Tuner->TunerRegs[23].Reg_Num = 41 ; + Tuner->TunerRegs[23].Reg_Val = 0x00 ; + + Tuner->TunerRegs[24].Reg_Num = 42 ; + Tuner->TunerRegs[24].Reg_Val = 0xF8 ; + + Tuner->TunerRegs[25].Reg_Num = 43 ; + Tuner->TunerRegs[25].Reg_Val = 0x43 ; + + Tuner->TunerRegs[26].Reg_Num = 44 ; + Tuner->TunerRegs[26].Reg_Val = 0x20 ; + + Tuner->TunerRegs[27].Reg_Num = 45 ; + Tuner->TunerRegs[27].Reg_Val = 0x80 ; + + Tuner->TunerRegs[28].Reg_Num = 46 ; + Tuner->TunerRegs[28].Reg_Val = 0x88 ; + + Tuner->TunerRegs[29].Reg_Num = 47 ; + Tuner->TunerRegs[29].Reg_Val = 0x86 ; + + Tuner->TunerRegs[30].Reg_Num = 48 ; + Tuner->TunerRegs[30].Reg_Val = 0x00 ; + + Tuner->TunerRegs[31].Reg_Num = 49 ; + Tuner->TunerRegs[31].Reg_Val = 0x00 ; + + Tuner->TunerRegs[32].Reg_Num = 53 ; + Tuner->TunerRegs[32].Reg_Val = 0x94 ; + + Tuner->TunerRegs[33].Reg_Num = 54 ; + Tuner->TunerRegs[33].Reg_Val = 0xFA ; + + Tuner->TunerRegs[34].Reg_Num = 55 ; + Tuner->TunerRegs[34].Reg_Val = 0x92 ; + + Tuner->TunerRegs[35].Reg_Num = 56 ; + Tuner->TunerRegs[35].Reg_Val = 0x80 ; + + Tuner->TunerRegs[36].Reg_Num = 57 ; + Tuner->TunerRegs[36].Reg_Val = 0x41 ; + + Tuner->TunerRegs[37].Reg_Num = 58 ; + Tuner->TunerRegs[37].Reg_Val = 0xDB ; + + Tuner->TunerRegs[38].Reg_Num = 59 ; + Tuner->TunerRegs[38].Reg_Val = 0x00 ; + + Tuner->TunerRegs[39].Reg_Num = 60 ; + Tuner->TunerRegs[39].Reg_Val = 0x00 ; + + Tuner->TunerRegs[40].Reg_Num = 61 ; + Tuner->TunerRegs[40].Reg_Val = 0x00 ; + + Tuner->TunerRegs[41].Reg_Num = 62 ; + Tuner->TunerRegs[41].Reg_Val = 0x00 ; + + Tuner->TunerRegs[42].Reg_Num = 65 ; + Tuner->TunerRegs[42].Reg_Val = 0xF8 ; + + Tuner->TunerRegs[43].Reg_Num = 66 ; + Tuner->TunerRegs[43].Reg_Val = 0xE4 ; + + Tuner->TunerRegs[44].Reg_Num = 67 ; + Tuner->TunerRegs[44].Reg_Val = 0x90 ; + + Tuner->TunerRegs[45].Reg_Num = 68 ; + Tuner->TunerRegs[45].Reg_Val = 0xC0 ; + + Tuner->TunerRegs[46].Reg_Num = 69 ; + Tuner->TunerRegs[46].Reg_Val = 0x01 ; + + Tuner->TunerRegs[47].Reg_Num = 70 ; + Tuner->TunerRegs[47].Reg_Val = 0x50 ; + + Tuner->TunerRegs[48].Reg_Num = 71 ; + Tuner->TunerRegs[48].Reg_Val = 0x06 ; + + Tuner->TunerRegs[49].Reg_Num = 72 ; + Tuner->TunerRegs[49].Reg_Val = 0x00 ; + + Tuner->TunerRegs[50].Reg_Num = 73 ; + Tuner->TunerRegs[50].Reg_Val = 0x20 ; + + Tuner->TunerRegs[51].Reg_Num = 76 ; + Tuner->TunerRegs[51].Reg_Val = 0xBB ; + + Tuner->TunerRegs[52].Reg_Num = 77 ; + Tuner->TunerRegs[52].Reg_Val = 0x13 ; + + Tuner->TunerRegs[53].Reg_Num = 81 ; + Tuner->TunerRegs[53].Reg_Val = 0x04 ; + + Tuner->TunerRegs[54].Reg_Num = 82 ; + Tuner->TunerRegs[54].Reg_Val = 0x75 ; + + Tuner->TunerRegs[55].Reg_Num = 83 ; + Tuner->TunerRegs[55].Reg_Val = 0x00 ; + + Tuner->TunerRegs[56].Reg_Num = 84 ; + Tuner->TunerRegs[56].Reg_Val = 0x00 ; + + Tuner->TunerRegs[57].Reg_Num = 85 ; + Tuner->TunerRegs[57].Reg_Val = 0x00 ; + + Tuner->TunerRegs[58].Reg_Num = 91 ; + Tuner->TunerRegs[58].Reg_Val = 0x70 ; + + Tuner->TunerRegs[59].Reg_Num = 92 ; + Tuner->TunerRegs[59].Reg_Val = 0x00 ; + + Tuner->TunerRegs[60].Reg_Num = 93 ; + Tuner->TunerRegs[60].Reg_Val = 0x00 ; + + Tuner->TunerRegs[61].Reg_Num = 94 ; + Tuner->TunerRegs[61].Reg_Val = 0x00 ; + + Tuner->TunerRegs[62].Reg_Num = 95 ; + Tuner->TunerRegs[62].Reg_Val = 0x0C ; + + Tuner->TunerRegs[63].Reg_Num = 96 ; + Tuner->TunerRegs[63].Reg_Val = 0x00 ; + + Tuner->TunerRegs[64].Reg_Num = 97 ; + Tuner->TunerRegs[64].Reg_Val = 0x00 ; + + Tuner->TunerRegs[65].Reg_Num = 98 ; + Tuner->TunerRegs[65].Reg_Val = 0xE2 ; + + Tuner->TunerRegs[66].Reg_Num = 99 ; + Tuner->TunerRegs[66].Reg_Val = 0x00 ; + + Tuner->TunerRegs[67].Reg_Num = 100 ; + Tuner->TunerRegs[67].Reg_Val = 0x00 ; + + Tuner->TunerRegs[68].Reg_Num = 101 ; + Tuner->TunerRegs[68].Reg_Val = 0x12 ; + + Tuner->TunerRegs[69].Reg_Num = 102 ; + Tuner->TunerRegs[69].Reg_Val = 0x80 ; + + Tuner->TunerRegs[70].Reg_Num = 103 ; + Tuner->TunerRegs[70].Reg_Val = 0x32 ; + + Tuner->TunerRegs[71].Reg_Num = 104 ; + Tuner->TunerRegs[71].Reg_Val = 0xB4 ; + + Tuner->TunerRegs[72].Reg_Num = 105 ; + Tuner->TunerRegs[72].Reg_Val = 0x60 ; + + Tuner->TunerRegs[73].Reg_Num = 106 ; + Tuner->TunerRegs[73].Reg_Val = 0x83 ; + + Tuner->TunerRegs[74].Reg_Num = 107 ; + Tuner->TunerRegs[74].Reg_Val = 0x84 ; + + Tuner->TunerRegs[75].Reg_Num = 108 ; + Tuner->TunerRegs[75].Reg_Val = 0x9C ; + + Tuner->TunerRegs[76].Reg_Num = 109 ; + Tuner->TunerRegs[76].Reg_Val = 0x02 ; + + Tuner->TunerRegs[77].Reg_Num = 110 ; + Tuner->TunerRegs[77].Reg_Val = 0x81 ; + + Tuner->TunerRegs[78].Reg_Num = 111 ; + Tuner->TunerRegs[78].Reg_Val = 0xC0 ; + + Tuner->TunerRegs[79].Reg_Num = 112 ; + Tuner->TunerRegs[79].Reg_Val = 0x10 ; + + Tuner->TunerRegs[80].Reg_Num = 131 ; + Tuner->TunerRegs[80].Reg_Val = 0x8A ; + + Tuner->TunerRegs[81].Reg_Num = 132 ; + Tuner->TunerRegs[81].Reg_Val = 0x10 ; + + Tuner->TunerRegs[82].Reg_Num = 133 ; + Tuner->TunerRegs[82].Reg_Val = 0x24 ; + + Tuner->TunerRegs[83].Reg_Num = 134 ; + Tuner->TunerRegs[83].Reg_Val = 0x00 ; + + Tuner->TunerRegs[84].Reg_Num = 135 ; + Tuner->TunerRegs[84].Reg_Val = 0x00 ; + + Tuner->TunerRegs[85].Reg_Num = 136 ; + Tuner->TunerRegs[85].Reg_Val = 0x7E ; + + Tuner->TunerRegs[86].Reg_Num = 137 ; + Tuner->TunerRegs[86].Reg_Val = 0x40 ; + + Tuner->TunerRegs[87].Reg_Num = 138 ; + Tuner->TunerRegs[87].Reg_Val = 0x38 ; + + Tuner->TunerRegs[88].Reg_Num = 146 ; + Tuner->TunerRegs[88].Reg_Val = 0xF6 ; + + Tuner->TunerRegs[89].Reg_Num = 147 ; + Tuner->TunerRegs[89].Reg_Val = 0x1A ; + + Tuner->TunerRegs[90].Reg_Num = 148 ; + Tuner->TunerRegs[90].Reg_Val = 0x62 ; + + Tuner->TunerRegs[91].Reg_Num = 149 ; + Tuner->TunerRegs[91].Reg_Val = 0x33 ; + + Tuner->TunerRegs[92].Reg_Num = 150 ; + Tuner->TunerRegs[92].Reg_Val = 0x80 ; + + Tuner->TunerRegs[93].Reg_Num = 156 ; + Tuner->TunerRegs[93].Reg_Val = 0x56 ; + + Tuner->TunerRegs[94].Reg_Num = 157 ; + Tuner->TunerRegs[94].Reg_Val = 0x17 ; + + Tuner->TunerRegs[95].Reg_Num = 158 ; + Tuner->TunerRegs[95].Reg_Val = 0xA9 ; + + Tuner->TunerRegs[96].Reg_Num = 159 ; + Tuner->TunerRegs[96].Reg_Val = 0x00 ; + + Tuner->TunerRegs[97].Reg_Num = 160 ; + Tuner->TunerRegs[97].Reg_Val = 0x00 ; + + Tuner->TunerRegs[98].Reg_Num = 161 ; + Tuner->TunerRegs[98].Reg_Val = 0x00 ; + + Tuner->TunerRegs[99].Reg_Num = 162 ; + Tuner->TunerRegs[99].Reg_Val = 0x40 ; + + Tuner->TunerRegs[100].Reg_Num = 166 ; + Tuner->TunerRegs[100].Reg_Val = 0xAE ; + + Tuner->TunerRegs[101].Reg_Num = 167 ; + Tuner->TunerRegs[101].Reg_Val = 0x1B ; + + Tuner->TunerRegs[102].Reg_Num = 168 ; + Tuner->TunerRegs[102].Reg_Val = 0xF2 ; + + Tuner->TunerRegs[103].Reg_Num = 195 ; + Tuner->TunerRegs[103].Reg_Val = 0x00 ; + + return 0 ; +} + +_u16 MXL5005_ControlInit (Tuner_struct *Tuner) +{ + Tuner->Init_Ctrl_Num = INITCTRL_NUM ; + + Tuner->Init_Ctrl[0].Ctrl_Num = DN_IQTN_AMP_CUT ; + Tuner->Init_Ctrl[0].size = 1 ; + Tuner->Init_Ctrl[0].addr[0] = 73; + Tuner->Init_Ctrl[0].bit[0] = 7; + Tuner->Init_Ctrl[0].val[0] = 0; + + Tuner->Init_Ctrl[1].Ctrl_Num = BB_MODE ; + Tuner->Init_Ctrl[1].size = 1 ; + Tuner->Init_Ctrl[1].addr[0] = 53; + Tuner->Init_Ctrl[1].bit[0] = 2; + Tuner->Init_Ctrl[1].val[0] = 1; + + Tuner->Init_Ctrl[2].Ctrl_Num = BB_BUF ; + Tuner->Init_Ctrl[2].size = 2 ; + Tuner->Init_Ctrl[2].addr[0] = 53; + Tuner->Init_Ctrl[2].bit[0] = 1; + Tuner->Init_Ctrl[2].val[0] = 0; + Tuner->Init_Ctrl[2].addr[1] = 57; + Tuner->Init_Ctrl[2].bit[1] = 0; + Tuner->Init_Ctrl[2].val[1] = 1; + + Tuner->Init_Ctrl[3].Ctrl_Num = BB_BUF_OA ; + Tuner->Init_Ctrl[3].size = 1 ; + Tuner->Init_Ctrl[3].addr[0] = 53; + Tuner->Init_Ctrl[3].bit[0] = 0; + Tuner->Init_Ctrl[3].val[0] = 0; + + Tuner->Init_Ctrl[4].Ctrl_Num = BB_ALPF_BANDSELECT ; + Tuner->Init_Ctrl[4].size = 3 ; + Tuner->Init_Ctrl[4].addr[0] = 53; + Tuner->Init_Ctrl[4].bit[0] = 5; + Tuner->Init_Ctrl[4].val[0] = 0; + Tuner->Init_Ctrl[4].addr[1] = 53; + Tuner->Init_Ctrl[4].bit[1] = 6; + Tuner->Init_Ctrl[4].val[1] = 0; + Tuner->Init_Ctrl[4].addr[2] = 53; + Tuner->Init_Ctrl[4].bit[2] = 7; + Tuner->Init_Ctrl[4].val[2] = 1; + + Tuner->Init_Ctrl[5].Ctrl_Num = BB_IQSWAP ; + Tuner->Init_Ctrl[5].size = 1 ; + Tuner->Init_Ctrl[5].addr[0] = 59; + Tuner->Init_Ctrl[5].bit[0] = 0; + Tuner->Init_Ctrl[5].val[0] = 0; + + Tuner->Init_Ctrl[6].Ctrl_Num = BB_DLPF_BANDSEL ; + Tuner->Init_Ctrl[6].size = 2 ; + Tuner->Init_Ctrl[6].addr[0] = 53; + Tuner->Init_Ctrl[6].bit[0] = 3; + Tuner->Init_Ctrl[6].val[0] = 0; + Tuner->Init_Ctrl[6].addr[1] = 53; + Tuner->Init_Ctrl[6].bit[1] = 4; + Tuner->Init_Ctrl[6].val[1] = 1; + + Tuner->Init_Ctrl[7].Ctrl_Num = RFSYN_CHP_GAIN ; + Tuner->Init_Ctrl[7].size = 4 ; + Tuner->Init_Ctrl[7].addr[0] = 22; + Tuner->Init_Ctrl[7].bit[0] = 4; + Tuner->Init_Ctrl[7].val[0] = 0; + Tuner->Init_Ctrl[7].addr[1] = 22; + Tuner->Init_Ctrl[7].bit[1] = 5; + Tuner->Init_Ctrl[7].val[1] = 1; + Tuner->Init_Ctrl[7].addr[2] = 22; + Tuner->Init_Ctrl[7].bit[2] = 6; + Tuner->Init_Ctrl[7].val[2] = 1; + Tuner->Init_Ctrl[7].addr[3] = 22; + Tuner->Init_Ctrl[7].bit[3] = 7; + Tuner->Init_Ctrl[7].val[3] = 0; + + Tuner->Init_Ctrl[8].Ctrl_Num = RFSYN_EN_CHP_HIGAIN ; + Tuner->Init_Ctrl[8].size = 1 ; + Tuner->Init_Ctrl[8].addr[0] = 22; + Tuner->Init_Ctrl[8].bit[0] = 2; + Tuner->Init_Ctrl[8].val[0] = 0; + + Tuner->Init_Ctrl[9].Ctrl_Num = AGC_IF ; + Tuner->Init_Ctrl[9].size = 4 ; + Tuner->Init_Ctrl[9].addr[0] = 76; + Tuner->Init_Ctrl[9].bit[0] = 0; + Tuner->Init_Ctrl[9].val[0] = 1; + Tuner->Init_Ctrl[9].addr[1] = 76; + Tuner->Init_Ctrl[9].bit[1] = 1; + Tuner->Init_Ctrl[9].val[1] = 1; + Tuner->Init_Ctrl[9].addr[2] = 76; + Tuner->Init_Ctrl[9].bit[2] = 2; + Tuner->Init_Ctrl[9].val[2] = 0; + Tuner->Init_Ctrl[9].addr[3] = 76; + Tuner->Init_Ctrl[9].bit[3] = 3; + Tuner->Init_Ctrl[9].val[3] = 1; + + Tuner->Init_Ctrl[10].Ctrl_Num = AGC_RF ; + Tuner->Init_Ctrl[10].size = 4 ; + Tuner->Init_Ctrl[10].addr[0] = 76; + Tuner->Init_Ctrl[10].bit[0] = 4; + Tuner->Init_Ctrl[10].val[0] = 1; + Tuner->Init_Ctrl[10].addr[1] = 76; + Tuner->Init_Ctrl[10].bit[1] = 5; + Tuner->Init_Ctrl[10].val[1] = 1; + Tuner->Init_Ctrl[10].addr[2] = 76; + Tuner->Init_Ctrl[10].bit[2] = 6; + Tuner->Init_Ctrl[10].val[2] = 0; + Tuner->Init_Ctrl[10].addr[3] = 76; + Tuner->Init_Ctrl[10].bit[3] = 7; + Tuner->Init_Ctrl[10].val[3] = 1; + + Tuner->Init_Ctrl[11].Ctrl_Num = IF_DIVVAL ; + Tuner->Init_Ctrl[11].size = 5 ; + Tuner->Init_Ctrl[11].addr[0] = 43; + Tuner->Init_Ctrl[11].bit[0] = 3; + Tuner->Init_Ctrl[11].val[0] = 0; + Tuner->Init_Ctrl[11].addr[1] = 43; + Tuner->Init_Ctrl[11].bit[1] = 4; + Tuner->Init_Ctrl[11].val[1] = 0; + Tuner->Init_Ctrl[11].addr[2] = 43; + Tuner->Init_Ctrl[11].bit[2] = 5; + Tuner->Init_Ctrl[11].val[2] = 0; + Tuner->Init_Ctrl[11].addr[3] = 43; + Tuner->Init_Ctrl[11].bit[3] = 6; + Tuner->Init_Ctrl[11].val[3] = 1; + Tuner->Init_Ctrl[11].addr[4] = 43; + Tuner->Init_Ctrl[11].bit[4] = 7; + Tuner->Init_Ctrl[11].val[4] = 0; + + Tuner->Init_Ctrl[12].Ctrl_Num = IF_VCO_BIAS ; + Tuner->Init_Ctrl[12].size = 6 ; + Tuner->Init_Ctrl[12].addr[0] = 44; + Tuner->Init_Ctrl[12].bit[0] = 2; + Tuner->Init_Ctrl[12].val[0] = 0; + Tuner->Init_Ctrl[12].addr[1] = 44; + Tuner->Init_Ctrl[12].bit[1] = 3; + Tuner->Init_Ctrl[12].val[1] = 0; + Tuner->Init_Ctrl[12].addr[2] = 44; + Tuner->Init_Ctrl[12].bit[2] = 4; + Tuner->Init_Ctrl[12].val[2] = 0; + Tuner->Init_Ctrl[12].addr[3] = 44; + Tuner->Init_Ctrl[12].bit[3] = 5; + Tuner->Init_Ctrl[12].val[3] = 1; + Tuner->Init_Ctrl[12].addr[4] = 44; + Tuner->Init_Ctrl[12].bit[4] = 6; + Tuner->Init_Ctrl[12].val[4] = 0; + Tuner->Init_Ctrl[12].addr[5] = 44; + Tuner->Init_Ctrl[12].bit[5] = 7; + Tuner->Init_Ctrl[12].val[5] = 0; + + Tuner->Init_Ctrl[13].Ctrl_Num = CHCAL_INT_MOD_IF ; + Tuner->Init_Ctrl[13].size = 7 ; + Tuner->Init_Ctrl[13].addr[0] = 11; + Tuner->Init_Ctrl[13].bit[0] = 0; + Tuner->Init_Ctrl[13].val[0] = 1; + Tuner->Init_Ctrl[13].addr[1] = 11; + Tuner->Init_Ctrl[13].bit[1] = 1; + Tuner->Init_Ctrl[13].val[1] = 0; + Tuner->Init_Ctrl[13].addr[2] = 11; + Tuner->Init_Ctrl[13].bit[2] = 2; + Tuner->Init_Ctrl[13].val[2] = 0; + Tuner->Init_Ctrl[13].addr[3] = 11; + Tuner->Init_Ctrl[13].bit[3] = 3; + Tuner->Init_Ctrl[13].val[3] = 1; + Tuner->Init_Ctrl[13].addr[4] = 11; + Tuner->Init_Ctrl[13].bit[4] = 4; + Tuner->Init_Ctrl[13].val[4] = 1; + Tuner->Init_Ctrl[13].addr[5] = 11; + Tuner->Init_Ctrl[13].bit[5] = 5; + Tuner->Init_Ctrl[13].val[5] = 0; + Tuner->Init_Ctrl[13].addr[6] = 11; + Tuner->Init_Ctrl[13].bit[6] = 6; + Tuner->Init_Ctrl[13].val[6] = 0; + + Tuner->Init_Ctrl[14].Ctrl_Num = CHCAL_FRAC_MOD_IF ; + Tuner->Init_Ctrl[14].size = 16 ; + Tuner->Init_Ctrl[14].addr[0] = 13; + Tuner->Init_Ctrl[14].bit[0] = 0; + Tuner->Init_Ctrl[14].val[0] = 0; + Tuner->Init_Ctrl[14].addr[1] = 13; + Tuner->Init_Ctrl[14].bit[1] = 1; + Tuner->Init_Ctrl[14].val[1] = 0; + Tuner->Init_Ctrl[14].addr[2] = 13; + Tuner->Init_Ctrl[14].bit[2] = 2; + Tuner->Init_Ctrl[14].val[2] = 0; + Tuner->Init_Ctrl[14].addr[3] = 13; + Tuner->Init_Ctrl[14].bit[3] = 3; + Tuner->Init_Ctrl[14].val[3] = 0; + Tuner->Init_Ctrl[14].addr[4] = 13; + Tuner->Init_Ctrl[14].bit[4] = 4; + Tuner->Init_Ctrl[14].val[4] = 0; + Tuner->Init_Ctrl[14].addr[5] = 13; + Tuner->Init_Ctrl[14].bit[5] = 5; + Tuner->Init_Ctrl[14].val[5] = 0; + Tuner->Init_Ctrl[14].addr[6] = 13; + Tuner->Init_Ctrl[14].bit[6] = 6; + Tuner->Init_Ctrl[14].val[6] = 0; + Tuner->Init_Ctrl[14].addr[7] = 13; + Tuner->Init_Ctrl[14].bit[7] = 7; + Tuner->Init_Ctrl[14].val[7] = 0; + Tuner->Init_Ctrl[14].addr[8] = 12; + Tuner->Init_Ctrl[14].bit[8] = 0; + Tuner->Init_Ctrl[14].val[8] = 0; + Tuner->Init_Ctrl[14].addr[9] = 12; + Tuner->Init_Ctrl[14].bit[9] = 1; + Tuner->Init_Ctrl[14].val[9] = 0; + Tuner->Init_Ctrl[14].addr[10] = 12; + Tuner->Init_Ctrl[14].bit[10] = 2; + Tuner->Init_Ctrl[14].val[10] = 0; + Tuner->Init_Ctrl[14].addr[11] = 12; + Tuner->Init_Ctrl[14].bit[11] = 3; + Tuner->Init_Ctrl[14].val[11] = 0; + Tuner->Init_Ctrl[14].addr[12] = 12; + Tuner->Init_Ctrl[14].bit[12] = 4; + Tuner->Init_Ctrl[14].val[12] = 0; + Tuner->Init_Ctrl[14].addr[13] = 12; + Tuner->Init_Ctrl[14].bit[13] = 5; + Tuner->Init_Ctrl[14].val[13] = 1; + Tuner->Init_Ctrl[14].addr[14] = 12; + Tuner->Init_Ctrl[14].bit[14] = 6; + Tuner->Init_Ctrl[14].val[14] = 1; + Tuner->Init_Ctrl[14].addr[15] = 12; + Tuner->Init_Ctrl[14].bit[15] = 7; + Tuner->Init_Ctrl[14].val[15] = 0; + + Tuner->Init_Ctrl[15].Ctrl_Num = DRV_RES_SEL ; + Tuner->Init_Ctrl[15].size = 3 ; + Tuner->Init_Ctrl[15].addr[0] = 147; + Tuner->Init_Ctrl[15].bit[0] = 2; + Tuner->Init_Ctrl[15].val[0] = 0; + Tuner->Init_Ctrl[15].addr[1] = 147; + Tuner->Init_Ctrl[15].bit[1] = 3; + Tuner->Init_Ctrl[15].val[1] = 1; + Tuner->Init_Ctrl[15].addr[2] = 147; + Tuner->Init_Ctrl[15].bit[2] = 4; + Tuner->Init_Ctrl[15].val[2] = 1; + + Tuner->Init_Ctrl[16].Ctrl_Num = I_DRIVER ; + Tuner->Init_Ctrl[16].size = 2 ; + Tuner->Init_Ctrl[16].addr[0] = 147; + Tuner->Init_Ctrl[16].bit[0] = 0; + Tuner->Init_Ctrl[16].val[0] = 0; + Tuner->Init_Ctrl[16].addr[1] = 147; + Tuner->Init_Ctrl[16].bit[1] = 1; + Tuner->Init_Ctrl[16].val[1] = 1; + + Tuner->Init_Ctrl[17].Ctrl_Num = EN_AAF ; + Tuner->Init_Ctrl[17].size = 1 ; + Tuner->Init_Ctrl[17].addr[0] = 147; + Tuner->Init_Ctrl[17].bit[0] = 7; + Tuner->Init_Ctrl[17].val[0] = 0; + + Tuner->Init_Ctrl[18].Ctrl_Num = EN_3P ; + Tuner->Init_Ctrl[18].size = 1 ; + Tuner->Init_Ctrl[18].addr[0] = 147; + Tuner->Init_Ctrl[18].bit[0] = 6; + Tuner->Init_Ctrl[18].val[0] = 0; + + Tuner->Init_Ctrl[19].Ctrl_Num = EN_AUX_3P ; + Tuner->Init_Ctrl[19].size = 1 ; + Tuner->Init_Ctrl[19].addr[0] = 156; + Tuner->Init_Ctrl[19].bit[0] = 0; + Tuner->Init_Ctrl[19].val[0] = 0; + + Tuner->Init_Ctrl[20].Ctrl_Num = SEL_AAF_BAND ; + Tuner->Init_Ctrl[20].size = 1 ; + Tuner->Init_Ctrl[20].addr[0] = 147; + Tuner->Init_Ctrl[20].bit[0] = 5; + Tuner->Init_Ctrl[20].val[0] = 0; + + Tuner->Init_Ctrl[21].Ctrl_Num = SEQ_ENCLK16_CLK_OUT ; + Tuner->Init_Ctrl[21].size = 1 ; + Tuner->Init_Ctrl[21].addr[0] = 137; + Tuner->Init_Ctrl[21].bit[0] = 4; + Tuner->Init_Ctrl[21].val[0] = 0; + + Tuner->Init_Ctrl[22].Ctrl_Num = SEQ_SEL4_16B ; + Tuner->Init_Ctrl[22].size = 1 ; + Tuner->Init_Ctrl[22].addr[0] = 137; + Tuner->Init_Ctrl[22].bit[0] = 7; + Tuner->Init_Ctrl[22].val[0] = 0; + + Tuner->Init_Ctrl[23].Ctrl_Num = XTAL_CAPSELECT ; + Tuner->Init_Ctrl[23].size = 1 ; + Tuner->Init_Ctrl[23].addr[0] = 91; + Tuner->Init_Ctrl[23].bit[0] = 5; + Tuner->Init_Ctrl[23].val[0] = 1; + + Tuner->Init_Ctrl[24].Ctrl_Num = IF_SEL_DBL ; + Tuner->Init_Ctrl[24].size = 1 ; + Tuner->Init_Ctrl[24].addr[0] = 43; + Tuner->Init_Ctrl[24].bit[0] = 0; + Tuner->Init_Ctrl[24].val[0] = 1; + + Tuner->Init_Ctrl[25].Ctrl_Num = RFSYN_R_DIV ; + Tuner->Init_Ctrl[25].size = 2 ; + Tuner->Init_Ctrl[25].addr[0] = 22; + Tuner->Init_Ctrl[25].bit[0] = 0; + Tuner->Init_Ctrl[25].val[0] = 1; + Tuner->Init_Ctrl[25].addr[1] = 22; + Tuner->Init_Ctrl[25].bit[1] = 1; + Tuner->Init_Ctrl[25].val[1] = 1; + + Tuner->Init_Ctrl[26].Ctrl_Num = SEQ_EXTSYNTHCALIF ; + Tuner->Init_Ctrl[26].size = 1 ; + Tuner->Init_Ctrl[26].addr[0] = 134; + Tuner->Init_Ctrl[26].bit[0] = 2; + Tuner->Init_Ctrl[26].val[0] = 0; + + Tuner->Init_Ctrl[27].Ctrl_Num = SEQ_EXTDCCAL ; + Tuner->Init_Ctrl[27].size = 1 ; + Tuner->Init_Ctrl[27].addr[0] = 137; + Tuner->Init_Ctrl[27].bit[0] = 3; + Tuner->Init_Ctrl[27].val[0] = 0; + + Tuner->Init_Ctrl[28].Ctrl_Num = AGC_EN_RSSI ; + Tuner->Init_Ctrl[28].size = 1 ; + Tuner->Init_Ctrl[28].addr[0] = 77; + Tuner->Init_Ctrl[28].bit[0] = 7; + Tuner->Init_Ctrl[28].val[0] = 0; + + Tuner->Init_Ctrl[29].Ctrl_Num = RFA_ENCLKRFAGC ; + Tuner->Init_Ctrl[29].size = 1 ; + Tuner->Init_Ctrl[29].addr[0] = 166; + Tuner->Init_Ctrl[29].bit[0] = 7; + Tuner->Init_Ctrl[29].val[0] = 1; + + Tuner->Init_Ctrl[30].Ctrl_Num = RFA_RSSI_REFH ; + Tuner->Init_Ctrl[30].size = 3 ; + Tuner->Init_Ctrl[30].addr[0] = 166; + Tuner->Init_Ctrl[30].bit[0] = 0; + Tuner->Init_Ctrl[30].val[0] = 0; + Tuner->Init_Ctrl[30].addr[1] = 166; + Tuner->Init_Ctrl[30].bit[1] = 1; + Tuner->Init_Ctrl[30].val[1] = 1; + Tuner->Init_Ctrl[30].addr[2] = 166; + Tuner->Init_Ctrl[30].bit[2] = 2; + Tuner->Init_Ctrl[30].val[2] = 1; + + Tuner->Init_Ctrl[31].Ctrl_Num = RFA_RSSI_REF ; + Tuner->Init_Ctrl[31].size = 3 ; + Tuner->Init_Ctrl[31].addr[0] = 166; + Tuner->Init_Ctrl[31].bit[0] = 3; + Tuner->Init_Ctrl[31].val[0] = 1; + Tuner->Init_Ctrl[31].addr[1] = 166; + Tuner->Init_Ctrl[31].bit[1] = 4; + Tuner->Init_Ctrl[31].val[1] = 0; + Tuner->Init_Ctrl[31].addr[2] = 166; + Tuner->Init_Ctrl[31].bit[2] = 5; + Tuner->Init_Ctrl[31].val[2] = 1; + + Tuner->Init_Ctrl[32].Ctrl_Num = RFA_RSSI_REFL ; + Tuner->Init_Ctrl[32].size = 3 ; + Tuner->Init_Ctrl[32].addr[0] = 167; + Tuner->Init_Ctrl[32].bit[0] = 0; + Tuner->Init_Ctrl[32].val[0] = 1; + Tuner->Init_Ctrl[32].addr[1] = 167; + Tuner->Init_Ctrl[32].bit[1] = 1; + Tuner->Init_Ctrl[32].val[1] = 1; + Tuner->Init_Ctrl[32].addr[2] = 167; + Tuner->Init_Ctrl[32].bit[2] = 2; + Tuner->Init_Ctrl[32].val[2] = 0; + + Tuner->Init_Ctrl[33].Ctrl_Num = RFA_FLR ; + Tuner->Init_Ctrl[33].size = 4 ; + Tuner->Init_Ctrl[33].addr[0] = 168; + Tuner->Init_Ctrl[33].bit[0] = 0; + Tuner->Init_Ctrl[33].val[0] = 0; + Tuner->Init_Ctrl[33].addr[1] = 168; + Tuner->Init_Ctrl[33].bit[1] = 1; + Tuner->Init_Ctrl[33].val[1] = 1; + Tuner->Init_Ctrl[33].addr[2] = 168; + Tuner->Init_Ctrl[33].bit[2] = 2; + Tuner->Init_Ctrl[33].val[2] = 0; + Tuner->Init_Ctrl[33].addr[3] = 168; + Tuner->Init_Ctrl[33].bit[3] = 3; + Tuner->Init_Ctrl[33].val[3] = 0; + + Tuner->Init_Ctrl[34].Ctrl_Num = RFA_CEIL ; + Tuner->Init_Ctrl[34].size = 4 ; + Tuner->Init_Ctrl[34].addr[0] = 168; + Tuner->Init_Ctrl[34].bit[0] = 4; + Tuner->Init_Ctrl[34].val[0] = 1; + Tuner->Init_Ctrl[34].addr[1] = 168; + Tuner->Init_Ctrl[34].bit[1] = 5; + Tuner->Init_Ctrl[34].val[1] = 1; + Tuner->Init_Ctrl[34].addr[2] = 168; + Tuner->Init_Ctrl[34].bit[2] = 6; + Tuner->Init_Ctrl[34].val[2] = 1; + Tuner->Init_Ctrl[34].addr[3] = 168; + Tuner->Init_Ctrl[34].bit[3] = 7; + Tuner->Init_Ctrl[34].val[3] = 1; + + Tuner->Init_Ctrl[35].Ctrl_Num = SEQ_EXTIQFSMPULSE ; + Tuner->Init_Ctrl[35].size = 1 ; + Tuner->Init_Ctrl[35].addr[0] = 135; + Tuner->Init_Ctrl[35].bit[0] = 0; + Tuner->Init_Ctrl[35].val[0] = 0; + + Tuner->Init_Ctrl[36].Ctrl_Num = OVERRIDE_1 ; + Tuner->Init_Ctrl[36].size = 1 ; + Tuner->Init_Ctrl[36].addr[0] = 56; + Tuner->Init_Ctrl[36].bit[0] = 3; + Tuner->Init_Ctrl[36].val[0] = 0; + + Tuner->Init_Ctrl[37].Ctrl_Num = BB_INITSTATE_DLPF_TUNE ; + Tuner->Init_Ctrl[37].size = 7 ; + Tuner->Init_Ctrl[37].addr[0] = 59; + Tuner->Init_Ctrl[37].bit[0] = 1; + Tuner->Init_Ctrl[37].val[0] = 0; + Tuner->Init_Ctrl[37].addr[1] = 59; + Tuner->Init_Ctrl[37].bit[1] = 2; + Tuner->Init_Ctrl[37].val[1] = 0; + Tuner->Init_Ctrl[37].addr[2] = 59; + Tuner->Init_Ctrl[37].bit[2] = 3; + Tuner->Init_Ctrl[37].val[2] = 0; + Tuner->Init_Ctrl[37].addr[3] = 59; + Tuner->Init_Ctrl[37].bit[3] = 4; + Tuner->Init_Ctrl[37].val[3] = 0; + Tuner->Init_Ctrl[37].addr[4] = 59; + Tuner->Init_Ctrl[37].bit[4] = 5; + Tuner->Init_Ctrl[37].val[4] = 0; + Tuner->Init_Ctrl[37].addr[5] = 59; + Tuner->Init_Ctrl[37].bit[5] = 6; + Tuner->Init_Ctrl[37].val[5] = 0; + Tuner->Init_Ctrl[37].addr[6] = 59; + Tuner->Init_Ctrl[37].bit[6] = 7; + Tuner->Init_Ctrl[37].val[6] = 0; + + Tuner->Init_Ctrl[38].Ctrl_Num = TG_R_DIV ; + Tuner->Init_Ctrl[38].size = 6 ; + Tuner->Init_Ctrl[38].addr[0] = 32; + Tuner->Init_Ctrl[38].bit[0] = 2; + Tuner->Init_Ctrl[38].val[0] = 0; + Tuner->Init_Ctrl[38].addr[1] = 32; + Tuner->Init_Ctrl[38].bit[1] = 3; + Tuner->Init_Ctrl[38].val[1] = 0; + Tuner->Init_Ctrl[38].addr[2] = 32; + Tuner->Init_Ctrl[38].bit[2] = 4; + Tuner->Init_Ctrl[38].val[2] = 0; + Tuner->Init_Ctrl[38].addr[3] = 32; + Tuner->Init_Ctrl[38].bit[3] = 5; + Tuner->Init_Ctrl[38].val[3] = 0; + Tuner->Init_Ctrl[38].addr[4] = 32; + Tuner->Init_Ctrl[38].bit[4] = 6; + Tuner->Init_Ctrl[38].val[4] = 1; + Tuner->Init_Ctrl[38].addr[5] = 32; + Tuner->Init_Ctrl[38].bit[5] = 7; + Tuner->Init_Ctrl[38].val[5] = 0; + + Tuner->Init_Ctrl[39].Ctrl_Num = EN_CHP_LIN_B ; + Tuner->Init_Ctrl[39].size = 1 ; + Tuner->Init_Ctrl[39].addr[0] = 25; + Tuner->Init_Ctrl[39].bit[0] = 3; + Tuner->Init_Ctrl[39].val[0] = 1; + + + Tuner->CH_Ctrl_Num = CHCTRL_NUM ; + + Tuner->CH_Ctrl[0].Ctrl_Num = DN_POLY ; + Tuner->CH_Ctrl[0].size = 2 ; + Tuner->CH_Ctrl[0].addr[0] = 68; + Tuner->CH_Ctrl[0].bit[0] = 6; + Tuner->CH_Ctrl[0].val[0] = 1; + Tuner->CH_Ctrl[0].addr[1] = 68; + Tuner->CH_Ctrl[0].bit[1] = 7; + Tuner->CH_Ctrl[0].val[1] = 1; + + Tuner->CH_Ctrl[1].Ctrl_Num = DN_RFGAIN ; + Tuner->CH_Ctrl[1].size = 2 ; + Tuner->CH_Ctrl[1].addr[0] = 70; + Tuner->CH_Ctrl[1].bit[0] = 6; + Tuner->CH_Ctrl[1].val[0] = 1; + Tuner->CH_Ctrl[1].addr[1] = 70; + Tuner->CH_Ctrl[1].bit[1] = 7; + Tuner->CH_Ctrl[1].val[1] = 0; + + Tuner->CH_Ctrl[2].Ctrl_Num = DN_CAP_RFLPF ; + Tuner->CH_Ctrl[2].size = 9 ; + Tuner->CH_Ctrl[2].addr[0] = 69; + Tuner->CH_Ctrl[2].bit[0] = 5; + Tuner->CH_Ctrl[2].val[0] = 0; + Tuner->CH_Ctrl[2].addr[1] = 69; + Tuner->CH_Ctrl[2].bit[1] = 6; + Tuner->CH_Ctrl[2].val[1] = 0; + Tuner->CH_Ctrl[2].addr[2] = 69; + Tuner->CH_Ctrl[2].bit[2] = 7; + Tuner->CH_Ctrl[2].val[2] = 0; + Tuner->CH_Ctrl[2].addr[3] = 68; + Tuner->CH_Ctrl[2].bit[3] = 0; + Tuner->CH_Ctrl[2].val[3] = 0; + Tuner->CH_Ctrl[2].addr[4] = 68; + Tuner->CH_Ctrl[2].bit[4] = 1; + Tuner->CH_Ctrl[2].val[4] = 0; + Tuner->CH_Ctrl[2].addr[5] = 68; + Tuner->CH_Ctrl[2].bit[5] = 2; + Tuner->CH_Ctrl[2].val[5] = 0; + Tuner->CH_Ctrl[2].addr[6] = 68; + Tuner->CH_Ctrl[2].bit[6] = 3; + Tuner->CH_Ctrl[2].val[6] = 0; + Tuner->CH_Ctrl[2].addr[7] = 68; + Tuner->CH_Ctrl[2].bit[7] = 4; + Tuner->CH_Ctrl[2].val[7] = 0; + Tuner->CH_Ctrl[2].addr[8] = 68; + Tuner->CH_Ctrl[2].bit[8] = 5; + Tuner->CH_Ctrl[2].val[8] = 0; + + Tuner->CH_Ctrl[3].Ctrl_Num = DN_EN_VHFUHFBAR ; + Tuner->CH_Ctrl[3].size = 1 ; + Tuner->CH_Ctrl[3].addr[0] = 70; + Tuner->CH_Ctrl[3].bit[0] = 5; + Tuner->CH_Ctrl[3].val[0] = 0; + + Tuner->CH_Ctrl[4].Ctrl_Num = DN_GAIN_ADJUST ; + Tuner->CH_Ctrl[4].size = 3 ; + Tuner->CH_Ctrl[4].addr[0] = 73; + Tuner->CH_Ctrl[4].bit[0] = 4; + Tuner->CH_Ctrl[4].val[0] = 0; + Tuner->CH_Ctrl[4].addr[1] = 73; + Tuner->CH_Ctrl[4].bit[1] = 5; + Tuner->CH_Ctrl[4].val[1] = 1; + Tuner->CH_Ctrl[4].addr[2] = 73; + Tuner->CH_Ctrl[4].bit[2] = 6; + Tuner->CH_Ctrl[4].val[2] = 0; + + Tuner->CH_Ctrl[5].Ctrl_Num = DN_IQTNBUF_AMP ; + Tuner->CH_Ctrl[5].size = 4 ; + Tuner->CH_Ctrl[5].addr[0] = 70; + Tuner->CH_Ctrl[5].bit[0] = 0; + Tuner->CH_Ctrl[5].val[0] = 0; + Tuner->CH_Ctrl[5].addr[1] = 70; + Tuner->CH_Ctrl[5].bit[1] = 1; + Tuner->CH_Ctrl[5].val[1] = 0; + Tuner->CH_Ctrl[5].addr[2] = 70; + Tuner->CH_Ctrl[5].bit[2] = 2; + Tuner->CH_Ctrl[5].val[2] = 0; + Tuner->CH_Ctrl[5].addr[3] = 70; + Tuner->CH_Ctrl[5].bit[3] = 3; + Tuner->CH_Ctrl[5].val[3] = 0; + + Tuner->CH_Ctrl[6].Ctrl_Num = DN_IQTNGNBFBIAS_BST ; + Tuner->CH_Ctrl[6].size = 1 ; + Tuner->CH_Ctrl[6].addr[0] = 70; + Tuner->CH_Ctrl[6].bit[0] = 4; + Tuner->CH_Ctrl[6].val[0] = 1; + + Tuner->CH_Ctrl[7].Ctrl_Num = RFSYN_EN_OUTMUX ; + Tuner->CH_Ctrl[7].size = 1 ; + Tuner->CH_Ctrl[7].addr[0] = 111; + Tuner->CH_Ctrl[7].bit[0] = 4; + Tuner->CH_Ctrl[7].val[0] = 0; + + Tuner->CH_Ctrl[8].Ctrl_Num = RFSYN_SEL_VCO_OUT ; + Tuner->CH_Ctrl[8].size = 1 ; + Tuner->CH_Ctrl[8].addr[0] = 111; + Tuner->CH_Ctrl[8].bit[0] = 7; + Tuner->CH_Ctrl[8].val[0] = 1; + + Tuner->CH_Ctrl[9].Ctrl_Num = RFSYN_SEL_VCO_HI ; + Tuner->CH_Ctrl[9].size = 1 ; + Tuner->CH_Ctrl[9].addr[0] = 111; + Tuner->CH_Ctrl[9].bit[0] = 6; + Tuner->CH_Ctrl[9].val[0] = 1; + + Tuner->CH_Ctrl[10].Ctrl_Num = RFSYN_SEL_DIVM ; + Tuner->CH_Ctrl[10].size = 1 ; + Tuner->CH_Ctrl[10].addr[0] = 111; + Tuner->CH_Ctrl[10].bit[0] = 5; + Tuner->CH_Ctrl[10].val[0] = 0; + + Tuner->CH_Ctrl[11].Ctrl_Num = RFSYN_RF_DIV_BIAS ; + Tuner->CH_Ctrl[11].size = 2 ; + Tuner->CH_Ctrl[11].addr[0] = 110; + Tuner->CH_Ctrl[11].bit[0] = 0; + Tuner->CH_Ctrl[11].val[0] = 1; + Tuner->CH_Ctrl[11].addr[1] = 110; + Tuner->CH_Ctrl[11].bit[1] = 1; + Tuner->CH_Ctrl[11].val[1] = 0; + + Tuner->CH_Ctrl[12].Ctrl_Num = DN_SEL_FREQ ; + Tuner->CH_Ctrl[12].size = 3 ; + Tuner->CH_Ctrl[12].addr[0] = 69; + Tuner->CH_Ctrl[12].bit[0] = 2; + Tuner->CH_Ctrl[12].val[0] = 0; + Tuner->CH_Ctrl[12].addr[1] = 69; + Tuner->CH_Ctrl[12].bit[1] = 3; + Tuner->CH_Ctrl[12].val[1] = 0; + Tuner->CH_Ctrl[12].addr[2] = 69; + Tuner->CH_Ctrl[12].bit[2] = 4; + Tuner->CH_Ctrl[12].val[2] = 0; + + Tuner->CH_Ctrl[13].Ctrl_Num = RFSYN_VCO_BIAS ; + Tuner->CH_Ctrl[13].size = 6 ; + Tuner->CH_Ctrl[13].addr[0] = 110; + Tuner->CH_Ctrl[13].bit[0] = 2; + Tuner->CH_Ctrl[13].val[0] = 0; + Tuner->CH_Ctrl[13].addr[1] = 110; + Tuner->CH_Ctrl[13].bit[1] = 3; + Tuner->CH_Ctrl[13].val[1] = 0; + Tuner->CH_Ctrl[13].addr[2] = 110; + Tuner->CH_Ctrl[13].bit[2] = 4; + Tuner->CH_Ctrl[13].val[2] = 0; + Tuner->CH_Ctrl[13].addr[3] = 110; + Tuner->CH_Ctrl[13].bit[3] = 5; + Tuner->CH_Ctrl[13].val[3] = 0; + Tuner->CH_Ctrl[13].addr[4] = 110; + Tuner->CH_Ctrl[13].bit[4] = 6; + Tuner->CH_Ctrl[13].val[4] = 0; + Tuner->CH_Ctrl[13].addr[5] = 110; + Tuner->CH_Ctrl[13].bit[5] = 7; + Tuner->CH_Ctrl[13].val[5] = 1; + + Tuner->CH_Ctrl[14].Ctrl_Num = CHCAL_INT_MOD_RF ; + Tuner->CH_Ctrl[14].size = 7 ; + Tuner->CH_Ctrl[14].addr[0] = 14; + Tuner->CH_Ctrl[14].bit[0] = 0; + Tuner->CH_Ctrl[14].val[0] = 0; + Tuner->CH_Ctrl[14].addr[1] = 14; + Tuner->CH_Ctrl[14].bit[1] = 1; + Tuner->CH_Ctrl[14].val[1] = 0; + Tuner->CH_Ctrl[14].addr[2] = 14; + Tuner->CH_Ctrl[14].bit[2] = 2; + Tuner->CH_Ctrl[14].val[2] = 0; + Tuner->CH_Ctrl[14].addr[3] = 14; + Tuner->CH_Ctrl[14].bit[3] = 3; + Tuner->CH_Ctrl[14].val[3] = 0; + Tuner->CH_Ctrl[14].addr[4] = 14; + Tuner->CH_Ctrl[14].bit[4] = 4; + Tuner->CH_Ctrl[14].val[4] = 0; + Tuner->CH_Ctrl[14].addr[5] = 14; + Tuner->CH_Ctrl[14].bit[5] = 5; + Tuner->CH_Ctrl[14].val[5] = 0; + Tuner->CH_Ctrl[14].addr[6] = 14; + Tuner->CH_Ctrl[14].bit[6] = 6; + Tuner->CH_Ctrl[14].val[6] = 0; + + Tuner->CH_Ctrl[15].Ctrl_Num = CHCAL_FRAC_MOD_RF ; + Tuner->CH_Ctrl[15].size = 18 ; + Tuner->CH_Ctrl[15].addr[0] = 17; + Tuner->CH_Ctrl[15].bit[0] = 6; + Tuner->CH_Ctrl[15].val[0] = 0; + Tuner->CH_Ctrl[15].addr[1] = 17; + Tuner->CH_Ctrl[15].bit[1] = 7; + Tuner->CH_Ctrl[15].val[1] = 0; + Tuner->CH_Ctrl[15].addr[2] = 16; + Tuner->CH_Ctrl[15].bit[2] = 0; + Tuner->CH_Ctrl[15].val[2] = 0; + Tuner->CH_Ctrl[15].addr[3] = 16; + Tuner->CH_Ctrl[15].bit[3] = 1; + Tuner->CH_Ctrl[15].val[3] = 0; + Tuner->CH_Ctrl[15].addr[4] = 16; + Tuner->CH_Ctrl[15].bit[4] = 2; + Tuner->CH_Ctrl[15].val[4] = 0; + Tuner->CH_Ctrl[15].addr[5] = 16; + Tuner->CH_Ctrl[15].bit[5] = 3; + Tuner->CH_Ctrl[15].val[5] = 0; + Tuner->CH_Ctrl[15].addr[6] = 16; + Tuner->CH_Ctrl[15].bit[6] = 4; + Tuner->CH_Ctrl[15].val[6] = 0; + Tuner->CH_Ctrl[15].addr[7] = 16; + Tuner->CH_Ctrl[15].bit[7] = 5; + Tuner->CH_Ctrl[15].val[7] = 0; + Tuner->CH_Ctrl[15].addr[8] = 16; + Tuner->CH_Ctrl[15].bit[8] = 6; + Tuner->CH_Ctrl[15].val[8] = 0; + Tuner->CH_Ctrl[15].addr[9] = 16; + Tuner->CH_Ctrl[15].bit[9] = 7; + Tuner->CH_Ctrl[15].val[9] = 0; + Tuner->CH_Ctrl[15].addr[10] = 15; + Tuner->CH_Ctrl[15].bit[10] = 0; + Tuner->CH_Ctrl[15].val[10] = 0; + Tuner->CH_Ctrl[15].addr[11] = 15; + Tuner->CH_Ctrl[15].bit[11] = 1; + Tuner->CH_Ctrl[15].val[11] = 0; + Tuner->CH_Ctrl[15].addr[12] = 15; + Tuner->CH_Ctrl[15].bit[12] = 2; + Tuner->CH_Ctrl[15].val[12] = 0; + Tuner->CH_Ctrl[15].addr[13] = 15; + Tuner->CH_Ctrl[15].bit[13] = 3; + Tuner->CH_Ctrl[15].val[13] = 0; + Tuner->CH_Ctrl[15].addr[14] = 15; + Tuner->CH_Ctrl[15].bit[14] = 4; + Tuner->CH_Ctrl[15].val[14] = 0; + Tuner->CH_Ctrl[15].addr[15] = 15; + Tuner->CH_Ctrl[15].bit[15] = 5; + Tuner->CH_Ctrl[15].val[15] = 0; + Tuner->CH_Ctrl[15].addr[16] = 15; + Tuner->CH_Ctrl[15].bit[16] = 6; + Tuner->CH_Ctrl[15].val[16] = 1; + Tuner->CH_Ctrl[15].addr[17] = 15; + Tuner->CH_Ctrl[15].bit[17] = 7; + Tuner->CH_Ctrl[15].val[17] = 1; + + Tuner->CH_Ctrl[16].Ctrl_Num = RFSYN_LPF_R ; + Tuner->CH_Ctrl[16].size = 5 ; + Tuner->CH_Ctrl[16].addr[0] = 112; + Tuner->CH_Ctrl[16].bit[0] = 0; + Tuner->CH_Ctrl[16].val[0] = 0; + Tuner->CH_Ctrl[16].addr[1] = 112; + Tuner->CH_Ctrl[16].bit[1] = 1; + Tuner->CH_Ctrl[16].val[1] = 0; + Tuner->CH_Ctrl[16].addr[2] = 112; + Tuner->CH_Ctrl[16].bit[2] = 2; + Tuner->CH_Ctrl[16].val[2] = 0; + Tuner->CH_Ctrl[16].addr[3] = 112; + Tuner->CH_Ctrl[16].bit[3] = 3; + Tuner->CH_Ctrl[16].val[3] = 0; + Tuner->CH_Ctrl[16].addr[4] = 112; + Tuner->CH_Ctrl[16].bit[4] = 4; + Tuner->CH_Ctrl[16].val[4] = 1; + + Tuner->CH_Ctrl[17].Ctrl_Num = CHCAL_EN_INT_RF ; + Tuner->CH_Ctrl[17].size = 1 ; + Tuner->CH_Ctrl[17].addr[0] = 14; + Tuner->CH_Ctrl[17].bit[0] = 7; + Tuner->CH_Ctrl[17].val[0] = 0; + + Tuner->CH_Ctrl[18].Ctrl_Num = TG_LO_DIVVAL ; + Tuner->CH_Ctrl[18].size = 4 ; + Tuner->CH_Ctrl[18].addr[0] = 107; + Tuner->CH_Ctrl[18].bit[0] = 3; + Tuner->CH_Ctrl[18].val[0] = 0; + Tuner->CH_Ctrl[18].addr[1] = 107; + Tuner->CH_Ctrl[18].bit[1] = 4; + Tuner->CH_Ctrl[18].val[1] = 0; + Tuner->CH_Ctrl[18].addr[2] = 107; + Tuner->CH_Ctrl[18].bit[2] = 5; + Tuner->CH_Ctrl[18].val[2] = 0; + Tuner->CH_Ctrl[18].addr[3] = 107; + Tuner->CH_Ctrl[18].bit[3] = 6; + Tuner->CH_Ctrl[18].val[3] = 0; + + Tuner->CH_Ctrl[19].Ctrl_Num = TG_LO_SELVAL ; + Tuner->CH_Ctrl[19].size = 3 ; + Tuner->CH_Ctrl[19].addr[0] = 107; + Tuner->CH_Ctrl[19].bit[0] = 7; + Tuner->CH_Ctrl[19].val[0] = 1; + Tuner->CH_Ctrl[19].addr[1] = 106; + Tuner->CH_Ctrl[19].bit[1] = 0; + Tuner->CH_Ctrl[19].val[1] = 1; + Tuner->CH_Ctrl[19].addr[2] = 106; + Tuner->CH_Ctrl[19].bit[2] = 1; + Tuner->CH_Ctrl[19].val[2] = 1; + + Tuner->CH_Ctrl[20].Ctrl_Num = TG_DIV_VAL ; + Tuner->CH_Ctrl[20].size = 11 ; + Tuner->CH_Ctrl[20].addr[0] = 109; + Tuner->CH_Ctrl[20].bit[0] = 2; + Tuner->CH_Ctrl[20].val[0] = 0; + Tuner->CH_Ctrl[20].addr[1] = 109; + Tuner->CH_Ctrl[20].bit[1] = 3; + Tuner->CH_Ctrl[20].val[1] = 0; + Tuner->CH_Ctrl[20].addr[2] = 109; + Tuner->CH_Ctrl[20].bit[2] = 4; + Tuner->CH_Ctrl[20].val[2] = 0; + Tuner->CH_Ctrl[20].addr[3] = 109; + Tuner->CH_Ctrl[20].bit[3] = 5; + Tuner->CH_Ctrl[20].val[3] = 0; + Tuner->CH_Ctrl[20].addr[4] = 109; + Tuner->CH_Ctrl[20].bit[4] = 6; + Tuner->CH_Ctrl[20].val[4] = 0; + Tuner->CH_Ctrl[20].addr[5] = 109; + Tuner->CH_Ctrl[20].bit[5] = 7; + Tuner->CH_Ctrl[20].val[5] = 0; + Tuner->CH_Ctrl[20].addr[6] = 108; + Tuner->CH_Ctrl[20].bit[6] = 0; + Tuner->CH_Ctrl[20].val[6] = 0; + Tuner->CH_Ctrl[20].addr[7] = 108; + Tuner->CH_Ctrl[20].bit[7] = 1; + Tuner->CH_Ctrl[20].val[7] = 0; + Tuner->CH_Ctrl[20].addr[8] = 108; + Tuner->CH_Ctrl[20].bit[8] = 2; + Tuner->CH_Ctrl[20].val[8] = 1; + Tuner->CH_Ctrl[20].addr[9] = 108; + Tuner->CH_Ctrl[20].bit[9] = 3; + Tuner->CH_Ctrl[20].val[9] = 1; + Tuner->CH_Ctrl[20].addr[10] = 108; + Tuner->CH_Ctrl[20].bit[10] = 4; + Tuner->CH_Ctrl[20].val[10] = 1; + + Tuner->CH_Ctrl[21].Ctrl_Num = TG_VCO_BIAS ; + Tuner->CH_Ctrl[21].size = 6 ; + Tuner->CH_Ctrl[21].addr[0] = 106; + Tuner->CH_Ctrl[21].bit[0] = 2; + Tuner->CH_Ctrl[21].val[0] = 0; + Tuner->CH_Ctrl[21].addr[1] = 106; + Tuner->CH_Ctrl[21].bit[1] = 3; + Tuner->CH_Ctrl[21].val[1] = 0; + Tuner->CH_Ctrl[21].addr[2] = 106; + Tuner->CH_Ctrl[21].bit[2] = 4; + Tuner->CH_Ctrl[21].val[2] = 0; + Tuner->CH_Ctrl[21].addr[3] = 106; + Tuner->CH_Ctrl[21].bit[3] = 5; + Tuner->CH_Ctrl[21].val[3] = 0; + Tuner->CH_Ctrl[21].addr[4] = 106; + Tuner->CH_Ctrl[21].bit[4] = 6; + Tuner->CH_Ctrl[21].val[4] = 0; + Tuner->CH_Ctrl[21].addr[5] = 106; + Tuner->CH_Ctrl[21].bit[5] = 7; + Tuner->CH_Ctrl[21].val[5] = 1; + + Tuner->CH_Ctrl[22].Ctrl_Num = SEQ_EXTPOWERUP ; + Tuner->CH_Ctrl[22].size = 1 ; + Tuner->CH_Ctrl[22].addr[0] = 138; + Tuner->CH_Ctrl[22].bit[0] = 4; + Tuner->CH_Ctrl[22].val[0] = 1; + + Tuner->CH_Ctrl[23].Ctrl_Num = OVERRIDE_2 ; + Tuner->CH_Ctrl[23].size = 1 ; + Tuner->CH_Ctrl[23].addr[0] = 17; + Tuner->CH_Ctrl[23].bit[0] = 5; + Tuner->CH_Ctrl[23].val[0] = 0; + + Tuner->CH_Ctrl[24].Ctrl_Num = OVERRIDE_3 ; + Tuner->CH_Ctrl[24].size = 1 ; + Tuner->CH_Ctrl[24].addr[0] = 111; + Tuner->CH_Ctrl[24].bit[0] = 3; + Tuner->CH_Ctrl[24].val[0] = 0; + + Tuner->CH_Ctrl[25].Ctrl_Num = OVERRIDE_4 ; + Tuner->CH_Ctrl[25].size = 1 ; + Tuner->CH_Ctrl[25].addr[0] = 112; + Tuner->CH_Ctrl[25].bit[0] = 7; + Tuner->CH_Ctrl[25].val[0] = 0; + + Tuner->CH_Ctrl[26].Ctrl_Num = SEQ_FSM_PULSE ; + Tuner->CH_Ctrl[26].size = 1 ; + Tuner->CH_Ctrl[26].addr[0] = 136; + Tuner->CH_Ctrl[26].bit[0] = 7; + Tuner->CH_Ctrl[26].val[0] = 0; + + Tuner->CH_Ctrl[27].Ctrl_Num = GPIO_4B ; + Tuner->CH_Ctrl[27].size = 1 ; + Tuner->CH_Ctrl[27].addr[0] = 149; + Tuner->CH_Ctrl[27].bit[0] = 7; + Tuner->CH_Ctrl[27].val[0] = 0; + + Tuner->CH_Ctrl[28].Ctrl_Num = GPIO_3B ; + Tuner->CH_Ctrl[28].size = 1 ; + Tuner->CH_Ctrl[28].addr[0] = 149; + Tuner->CH_Ctrl[28].bit[0] = 6; + Tuner->CH_Ctrl[28].val[0] = 0; + + Tuner->CH_Ctrl[29].Ctrl_Num = GPIO_4 ; + Tuner->CH_Ctrl[29].size = 1 ; + Tuner->CH_Ctrl[29].addr[0] = 149; + Tuner->CH_Ctrl[29].bit[0] = 5; + Tuner->CH_Ctrl[29].val[0] = 1; + + Tuner->CH_Ctrl[30].Ctrl_Num = GPIO_3 ; + Tuner->CH_Ctrl[30].size = 1 ; + Tuner->CH_Ctrl[30].addr[0] = 149; + Tuner->CH_Ctrl[30].bit[0] = 4; + Tuner->CH_Ctrl[30].val[0] = 1; + + Tuner->CH_Ctrl[31].Ctrl_Num = GPIO_1B ; + Tuner->CH_Ctrl[31].size = 1 ; + Tuner->CH_Ctrl[31].addr[0] = 149; + Tuner->CH_Ctrl[31].bit[0] = 3; + Tuner->CH_Ctrl[31].val[0] = 0; + + Tuner->CH_Ctrl[32].Ctrl_Num = DAC_A_ENABLE ; + Tuner->CH_Ctrl[32].size = 1 ; + Tuner->CH_Ctrl[32].addr[0] = 93; + Tuner->CH_Ctrl[32].bit[0] = 1; + Tuner->CH_Ctrl[32].val[0] = 0; + + Tuner->CH_Ctrl[33].Ctrl_Num = DAC_B_ENABLE ; + Tuner->CH_Ctrl[33].size = 1 ; + Tuner->CH_Ctrl[33].addr[0] = 93; + Tuner->CH_Ctrl[33].bit[0] = 0; + Tuner->CH_Ctrl[33].val[0] = 0; + + Tuner->CH_Ctrl[34].Ctrl_Num = DAC_DIN_A ; + Tuner->CH_Ctrl[34].size = 6 ; + Tuner->CH_Ctrl[34].addr[0] = 92; + Tuner->CH_Ctrl[34].bit[0] = 2; + Tuner->CH_Ctrl[34].val[0] = 0; + Tuner->CH_Ctrl[34].addr[1] = 92; + Tuner->CH_Ctrl[34].bit[1] = 3; + Tuner->CH_Ctrl[34].val[1] = 0; + Tuner->CH_Ctrl[34].addr[2] = 92; + Tuner->CH_Ctrl[34].bit[2] = 4; + Tuner->CH_Ctrl[34].val[2] = 0; + Tuner->CH_Ctrl[34].addr[3] = 92; + Tuner->CH_Ctrl[34].bit[3] = 5; + Tuner->CH_Ctrl[34].val[3] = 0; + Tuner->CH_Ctrl[34].addr[4] = 92; + Tuner->CH_Ctrl[34].bit[4] = 6; + Tuner->CH_Ctrl[34].val[4] = 0; + Tuner->CH_Ctrl[34].addr[5] = 92; + Tuner->CH_Ctrl[34].bit[5] = 7; + Tuner->CH_Ctrl[34].val[5] = 0; + + Tuner->CH_Ctrl[35].Ctrl_Num = DAC_DIN_B ; + Tuner->CH_Ctrl[35].size = 6 ; + Tuner->CH_Ctrl[35].addr[0] = 93; + Tuner->CH_Ctrl[35].bit[0] = 2; + Tuner->CH_Ctrl[35].val[0] = 0; + Tuner->CH_Ctrl[35].addr[1] = 93; + Tuner->CH_Ctrl[35].bit[1] = 3; + Tuner->CH_Ctrl[35].val[1] = 0; + Tuner->CH_Ctrl[35].addr[2] = 93; + Tuner->CH_Ctrl[35].bit[2] = 4; + Tuner->CH_Ctrl[35].val[2] = 0; + Tuner->CH_Ctrl[35].addr[3] = 93; + Tuner->CH_Ctrl[35].bit[3] = 5; + Tuner->CH_Ctrl[35].val[3] = 0; + Tuner->CH_Ctrl[35].addr[4] = 93; + Tuner->CH_Ctrl[35].bit[4] = 6; + Tuner->CH_Ctrl[35].val[4] = 0; + Tuner->CH_Ctrl[35].addr[5] = 93; + Tuner->CH_Ctrl[35].bit[5] = 7; + Tuner->CH_Ctrl[35].val[5] = 0; + +#ifdef _MXL_PRODUCTION + Tuner->CH_Ctrl[36].Ctrl_Num = RFSYN_EN_DIV ; + Tuner->CH_Ctrl[36].size = 1 ; + Tuner->CH_Ctrl[36].addr[0] = 109; + Tuner->CH_Ctrl[36].bit[0] = 1; + Tuner->CH_Ctrl[36].val[0] = 1; + + Tuner->CH_Ctrl[37].Ctrl_Num = RFSYN_DIVM ; + Tuner->CH_Ctrl[37].size = 2 ; + Tuner->CH_Ctrl[37].addr[0] = 112; + Tuner->CH_Ctrl[37].bit[0] = 5; + Tuner->CH_Ctrl[37].val[0] = 0; + Tuner->CH_Ctrl[37].addr[1] = 112; + Tuner->CH_Ctrl[37].bit[1] = 6; + Tuner->CH_Ctrl[37].val[1] = 0; + + Tuner->CH_Ctrl[38].Ctrl_Num = DN_BYPASS_AGC_I2C ; + Tuner->CH_Ctrl[38].size = 1 ; + Tuner->CH_Ctrl[38].addr[0] = 65; + Tuner->CH_Ctrl[38].bit[0] = 1; + Tuner->CH_Ctrl[38].val[0] = 0; +#endif + + return 0 ; +} + + + + + + + + + + + + + + + +// MaxLinear source code - MXL5005_c.cpp + + + +// MXL5005.cpp : Defines the initialization routines for the DLL. +// 2.6.12 + + +//#ifdef _MXL_HEADER +//#include "stdafx.h" +//#endif +//#include "MXL5005_c.h" + + +void InitTunerControls(Tuner_struct *Tuner) +{ + MXL5005_RegisterInit(Tuner) ; + MXL5005_ControlInit(Tuner) ; +#ifdef _MXL_INTERNAL + MXL5005_MXLControlInit(Tuner) ; +#endif +} + + + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL_ConfigTuner // +// // +// Description: Configure MXL5005Tuner structure for desired // +// Channel Bandwidth/Channel Frequency // +// // +// // +// Functions used: // +// MXL_SynthIFLO_Calc // +// // +// Inputs: // +// Tuner_struct: structure defined at higher level // +// Mode: Tuner Mode (Analog/Digital) // +// IF_Mode: IF Mode ( Zero/Low ) // +// Bandwidth: Filter Channel Bandwidth (in Hz) // +// IF_out: Desired IF out Frequency (in Hz) // +// Fxtal: Crystal Frerquency (in Hz) // +// TOP: 0: Dual AGC; Value: take over point // +// IF_OUT_LOAD: IF out load resistor (200/300 Ohms) // +// CLOCK_OUT: 0: Turn off clock out; 1: turn on clock out // +// DIV_OUT: 0: Div-1; 1: Div-4 // +// CAPSELECT: 0: Disable On-chip pulling cap; 1: Enable // +// EN_RSSI: 0: Disable RSSI; 1: Enable RSSI // +// // +// Outputs: // +// Tuner // +// // +// Return: // +// 0 : Successful // +// > 0 : Failed // +// // +/////////////////////////////////////////////////////////////////////////////// +_u16 MXL5005_TunerConfig(Tuner_struct *Tuner, + _u8 Mode, // 0: Analog Mode ; 1: Digital Mode + _u8 IF_mode, // for Analog Mode, 0: zero IF; 1: low IF + _u32 Bandwidth, // filter channel bandwidth (6, 7, 8) + _u32 IF_out, // Desired IF Out Frequency + _u32 Fxtal, // XTAL Frequency + _u8 AGC_Mode, // AGC Mode - Dual AGC: 0, Single AGC: 1 + _u16 TOP, // 0: Dual AGC; Value: take over point + _u16 IF_OUT_LOAD, // IF Out Load Resistor (200 / 300 Ohms) + _u8 CLOCK_OUT, // 0: turn off clock out; 1: turn on clock out + _u8 DIV_OUT, // 0: Div-1; 1: Div-4 + _u8 CAPSELECT, // 0: disable On-Chip pulling cap; 1: enable + _u8 EN_RSSI, // 0: disable RSSI; 1: enable RSSI + _u8 Mod_Type, // Modulation Type; + // 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable + _u8 TF_Type // Tracking Filter + // 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H + ) +{ + _u16 status = 0 ; + + Tuner->Mode = Mode ; + Tuner->IF_Mode = IF_mode ; + Tuner->Chan_Bandwidth = Bandwidth ; + Tuner->IF_OUT = IF_out ; + Tuner->Fxtal = Fxtal ; + Tuner->AGC_Mode = AGC_Mode ; + Tuner->TOP = TOP ; + Tuner->IF_OUT_LOAD = IF_OUT_LOAD ; + Tuner->CLOCK_OUT = CLOCK_OUT ; + Tuner->DIV_OUT = DIV_OUT ; + Tuner->CAPSELECT = CAPSELECT ; + Tuner->EN_RSSI = EN_RSSI ; + Tuner->Mod_Type = Mod_Type ; + Tuner->TF_Type = TF_Type ; + + + + // + // Initialize all the controls and registers + // + InitTunerControls (Tuner) ; + // + // Synthesizer LO frequency calculation + // + MXL_SynthIFLO_Calc( Tuner ) ; + + return status ; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL_SynthIFLO_Calc // +// // +// Description: Calculate Internal IF-LO Frequency // +// // +// Globals: // +// NONE // +// // +// Functions used: // +// NONE // +// // +// Inputs: // +// Tuner_struct: structure defined at higher level // +// // +// Outputs: // +// Tuner // +// // +// Return: // +// 0 : Successful // +// > 0 : Failed // +// // +/////////////////////////////////////////////////////////////////////////////// +void MXL_SynthIFLO_Calc(Tuner_struct *Tuner) +{ + if (Tuner->Mode == 1) // Digital Mode + { + Tuner->IF_LO = Tuner->IF_OUT ; + } + else // Analog Mode + { + if(Tuner->IF_Mode == 0) // Analog Zero IF mode + { + Tuner->IF_LO = Tuner->IF_OUT + 400000 ; + } + else // Analog Low IF mode + { + Tuner->IF_LO = Tuner->IF_OUT + Tuner->Chan_Bandwidth/2 ; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL_SynthRFTGLO_Calc // +// // +// Description: Calculate Internal RF-LO frequency and // +// internal Tone-Gen(TG)-LO frequency // +// // +// Globals: // +// NONE // +// // +// Functions used: // +// NONE // +// // +// Inputs: // +// Tuner_struct: structure defined at higher level // +// // +// Outputs: // +// Tuner // +// // +// Return: // +// 0 : Successful // +// > 0 : Failed // +// // +/////////////////////////////////////////////////////////////////////////////// +void MXL_SynthRFTGLO_Calc(Tuner_struct *Tuner) +{ + if (Tuner->Mode == 1) // Digital Mode + { + //remove 20.48MHz setting for 2.6.10 + Tuner->RF_LO = Tuner->RF_IN ; + Tuner->TG_LO = Tuner->RF_IN - 750000 ; //change for 2.6.6 + } + else // Analog Mode + { + if(Tuner->IF_Mode == 0) // Analog Zero IF mode + { + Tuner->RF_LO = Tuner->RF_IN - 400000 ; + Tuner->TG_LO = Tuner->RF_IN - 1750000 ; + } + else // Analog Low IF mode + { + Tuner->RF_LO = Tuner->RF_IN - Tuner->Chan_Bandwidth/2 ; + Tuner->TG_LO = Tuner->RF_IN - Tuner->Chan_Bandwidth + 500000 ; + } + } +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL_OverwriteICDefault // +// // +// Description: Overwrite the Default Register Setting // +// // +// // +// Functions used: // +// // +// Inputs: // +// Tuner_struct: structure defined at higher level // +// Outputs: // +// Tuner // +// // +// Return: // +// 0 : Successful // +// > 0 : Failed // +// // +/////////////////////////////////////////////////////////////////////////////// +_u16 MXL_OverwriteICDefault( Tuner_struct *Tuner) +{ + _u16 status = 0 ; + + status += MXL_ControlWrite(Tuner, OVERRIDE_1, 1) ; + status += MXL_ControlWrite(Tuner, OVERRIDE_2, 1) ; + status += MXL_ControlWrite(Tuner, OVERRIDE_3, 1) ; + status += MXL_ControlWrite(Tuner, OVERRIDE_4, 1) ; + + return status ; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL_BlockInit // +// // +// Description: Tuner Initialization as a function of 'User Settings' // +// * User settings in Tuner strcuture must be assigned // +// first // +// // +// Globals: // +// NONE // +// // +// Functions used: // +// Tuner_struct: structure defined at higher level // +// // +// Inputs: // +// Tuner : Tuner structure defined at higher level // +// // +// Outputs: // +// Tuner // +// // +// Return: // +// 0 : Successful // +// > 0 : Failed // +// // +/////////////////////////////////////////////////////////////////////////////// +_u16 MXL_BlockInit( Tuner_struct *Tuner ) +{ + _u16 status = 0 ; + + status += MXL_OverwriteICDefault(Tuner) ; + + // + // Downconverter Control + // Dig Ana + status += MXL_ControlWrite(Tuner, DN_IQTN_AMP_CUT, Tuner->Mode ? 1 : 0) ; + + // + // Filter Control + // Dig Ana + status += MXL_ControlWrite(Tuner, BB_MODE, Tuner->Mode ? 0 : 1) ; + status += MXL_ControlWrite(Tuner, BB_BUF, Tuner->Mode ? 3 : 2) ; + status += MXL_ControlWrite(Tuner, BB_BUF_OA, Tuner->Mode ? 1 : 0) ; + + status += MXL_ControlWrite(Tuner, BB_IQSWAP, Tuner->Mode ? 0 : 1) ; + status += MXL_ControlWrite(Tuner, BB_INITSTATE_DLPF_TUNE, 0) ; + + // Initialize Low-Pass Filter + if (Tuner->Mode) { // Digital Mode + switch (Tuner->Chan_Bandwidth) { + case 8000000: + status += MXL_ControlWrite(Tuner, BB_DLPF_BANDSEL, 0) ; + break ; + case 7000000: + status += MXL_ControlWrite(Tuner, BB_DLPF_BANDSEL, 2) ; + break ; + case 6000000: + status += MXL_ControlWrite(Tuner, BB_DLPF_BANDSEL, 3) ; + break ; + } + } else { // Analog Mode + switch (Tuner->Chan_Bandwidth) { + case 8000000: // Low Zero + status += MXL_ControlWrite(Tuner, BB_ALPF_BANDSELECT, (Tuner->IF_Mode ? 0 : 3)) ; + break ; + case 7000000: + status += MXL_ControlWrite(Tuner, BB_ALPF_BANDSELECT, (Tuner->IF_Mode ? 1 : 4)) ; + break ; + case 6000000: + status += MXL_ControlWrite(Tuner, BB_ALPF_BANDSELECT, (Tuner->IF_Mode ? 2 : 5)) ; + break ; + } + } + + // + // Charge Pump Control + // Dig Ana + status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, Tuner->Mode ? 5 : 8) ; + status += MXL_ControlWrite(Tuner, RFSYN_EN_CHP_HIGAIN, Tuner->Mode ? 1 : 1) ; + status += MXL_ControlWrite(Tuner, EN_CHP_LIN_B, Tuner->Mode ? 0 : 0) ; + + // + // AGC TOP Control + // + if (Tuner->AGC_Mode == 0) // Dual AGC + { + status += MXL_ControlWrite(Tuner, AGC_IF, 15) ; + status += MXL_ControlWrite(Tuner, AGC_RF, 15) ; + } + else // Single AGC Mode Dig Ana + status += MXL_ControlWrite(Tuner, AGC_RF, Tuner->Mode? 15 : 12) ; + + + if (Tuner->TOP == 55) // TOP == 5.5 + status += MXL_ControlWrite(Tuner, AGC_IF, 0x0) ; + + if (Tuner->TOP == 72) // TOP == 7.2 + status += MXL_ControlWrite(Tuner, AGC_IF, 0x1) ; + + if (Tuner->TOP == 92) // TOP == 9.2 + status += MXL_ControlWrite(Tuner, AGC_IF, 0x2) ; + + if (Tuner->TOP == 110) // TOP == 11.0 + status += MXL_ControlWrite(Tuner, AGC_IF, 0x3) ; + + if (Tuner->TOP == 129) // TOP == 12.9 + status += MXL_ControlWrite(Tuner, AGC_IF, 0x4) ; + + if (Tuner->TOP == 147) // TOP == 14.7 + status += MXL_ControlWrite(Tuner, AGC_IF, 0x5) ; + + if (Tuner->TOP == 168) // TOP == 16.8 + status += MXL_ControlWrite(Tuner, AGC_IF, 0x6) ; + + if (Tuner->TOP == 194) // TOP == 19.4 + status += MXL_ControlWrite(Tuner, AGC_IF, 0x7) ; + + if (Tuner->TOP == 212) // TOP == 21.2 + status += MXL_ControlWrite(Tuner, AGC_IF, 0x9) ; + + if (Tuner->TOP == 232) // TOP == 23.2 + status += MXL_ControlWrite(Tuner, AGC_IF, 0xA) ; + + if (Tuner->TOP == 252) // TOP == 25.2 + status += MXL_ControlWrite(Tuner, AGC_IF, 0xB) ; + + if (Tuner->TOP == 271) // TOP == 27.1 + status += MXL_ControlWrite(Tuner, AGC_IF, 0xC) ; + + if (Tuner->TOP == 292) // TOP == 29.2 + status += MXL_ControlWrite(Tuner, AGC_IF, 0xD) ; + + if (Tuner->TOP == 317) // TOP == 31.7 + status += MXL_ControlWrite(Tuner, AGC_IF, 0xE) ; + + if (Tuner->TOP == 349) // TOP == 34.9 + status += MXL_ControlWrite(Tuner, AGC_IF, 0xF) ; + + // + // IF Synthesizer Control + // + status += MXL_IFSynthInit( Tuner ) ; + + // + // IF UpConverter Control + if (Tuner->IF_OUT_LOAD == 200) + { + status += MXL_ControlWrite(Tuner, DRV_RES_SEL, 6) ; + status += MXL_ControlWrite(Tuner, I_DRIVER, 2) ; + } + if (Tuner->IF_OUT_LOAD == 300) + { + status += MXL_ControlWrite(Tuner, DRV_RES_SEL, 4) ; + status += MXL_ControlWrite(Tuner, I_DRIVER, 1) ; + } + + // + // Anti-Alias Filtering Control + // + // initialise Anti-Aliasing Filter + if (Tuner->Mode) {// Digital Mode + if (Tuner->IF_OUT >= 4000000UL && Tuner->IF_OUT <= 6280000UL) { + status += MXL_ControlWrite(Tuner, EN_AAF, 1) ; + status += MXL_ControlWrite(Tuner, EN_3P, 1) ; + status += MXL_ControlWrite(Tuner, EN_AUX_3P, 1) ; + status += MXL_ControlWrite(Tuner, SEL_AAF_BAND, 0) ; + } + if ((Tuner->IF_OUT == 36125000UL) || (Tuner->IF_OUT == 36150000UL)) { + status += MXL_ControlWrite(Tuner, EN_AAF, 1) ; + status += MXL_ControlWrite(Tuner, EN_3P, 1) ; + status += MXL_ControlWrite(Tuner, EN_AUX_3P, 1) ; + status += MXL_ControlWrite(Tuner, SEL_AAF_BAND, 1) ; + } + if (Tuner->IF_OUT > 36150000UL) { + status += MXL_ControlWrite(Tuner, EN_AAF, 0) ; + status += MXL_ControlWrite(Tuner, EN_3P, 1) ; + status += MXL_ControlWrite(Tuner, EN_AUX_3P, 1) ; + status += MXL_ControlWrite(Tuner, SEL_AAF_BAND, 1) ; + } + } else { // Analog Mode + if (Tuner->IF_OUT >= 4000000UL && Tuner->IF_OUT <= 5000000UL) + { + status += MXL_ControlWrite(Tuner, EN_AAF, 1) ; + status += MXL_ControlWrite(Tuner, EN_3P, 1) ; + status += MXL_ControlWrite(Tuner, EN_AUX_3P, 1) ; + status += MXL_ControlWrite(Tuner, SEL_AAF_BAND, 0) ; + } + if (Tuner->IF_OUT > 5000000UL) + { + status += MXL_ControlWrite(Tuner, EN_AAF, 0) ; + status += MXL_ControlWrite(Tuner, EN_3P, 0) ; + status += MXL_ControlWrite(Tuner, EN_AUX_3P, 0) ; + status += MXL_ControlWrite(Tuner, SEL_AAF_BAND, 0) ; + } + } + + // + // Demod Clock Out + // + if (Tuner->CLOCK_OUT) + status += MXL_ControlWrite(Tuner, SEQ_ENCLK16_CLK_OUT, 1) ; + else + status += MXL_ControlWrite(Tuner, SEQ_ENCLK16_CLK_OUT, 0) ; + + if (Tuner->DIV_OUT == 1) + status += MXL_ControlWrite(Tuner, SEQ_SEL4_16B, 1) ; + if (Tuner->DIV_OUT == 0) + status += MXL_ControlWrite(Tuner, SEQ_SEL4_16B, 0) ; + + // + // Crystal Control + // + if (Tuner->CAPSELECT) + status += MXL_ControlWrite(Tuner, XTAL_CAPSELECT, 1) ; + else + status += MXL_ControlWrite(Tuner, XTAL_CAPSELECT, 0) ; + + if (Tuner->Fxtal >= 12000000UL && Tuner->Fxtal <= 16000000UL) + status += MXL_ControlWrite(Tuner, IF_SEL_DBL, 1) ; + if (Tuner->Fxtal > 16000000UL && Tuner->Fxtal <= 32000000UL) + status += MXL_ControlWrite(Tuner, IF_SEL_DBL, 0) ; + + if (Tuner->Fxtal >= 12000000UL && Tuner->Fxtal <= 22000000UL) + status += MXL_ControlWrite(Tuner, RFSYN_R_DIV, 3) ; + if (Tuner->Fxtal > 22000000UL && Tuner->Fxtal <= 32000000UL) + status += MXL_ControlWrite(Tuner, RFSYN_R_DIV, 0) ; + + // + // Misc Controls + // + if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog LowIF mode + status += MXL_ControlWrite(Tuner, SEQ_EXTIQFSMPULSE, 0); + else + status += MXL_ControlWrite(Tuner, SEQ_EXTIQFSMPULSE, 1); + +// status += MXL_ControlRead(Tuner, IF_DIVVAL, &IF_DIVVAL_Val) ; + + // Set TG_R_DIV + status += MXL_ControlWrite(Tuner, TG_R_DIV, MXL_Ceiling(Tuner->Fxtal, 1000000)) ; + + // + // Apply Default value to BB_INITSTATE_DLPF_TUNE + // + + + + // + // RSSI Control + // + if(Tuner->EN_RSSI) + { + status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; + status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; + status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 1) ; + status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; + // RSSI reference point + status += MXL_ControlWrite(Tuner, RFA_RSSI_REF, 2) ; + status += MXL_ControlWrite(Tuner, RFA_RSSI_REFH, 3) ; + status += MXL_ControlWrite(Tuner, RFA_RSSI_REFL, 1) ; + // TOP point + status += MXL_ControlWrite(Tuner, RFA_FLR, 0) ; + status += MXL_ControlWrite(Tuner, RFA_CEIL, 12) ; + } + + // + // Modulation type bit settings + // Override the control values preset + // + if (Tuner->Mod_Type == MXL_DVBT) // DVB-T Mode + { + Tuner->AGC_Mode = 1 ; // Single AGC Mode + + // Enable RSSI + status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; + status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; + status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 1) ; + status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; + // RSSI reference point + status += MXL_ControlWrite(Tuner, RFA_RSSI_REF, 3) ; + status += MXL_ControlWrite(Tuner, RFA_RSSI_REFH, 5) ; + status += MXL_ControlWrite(Tuner, RFA_RSSI_REFL, 1) ; + // TOP point + status += MXL_ControlWrite(Tuner, RFA_FLR, 2) ; + status += MXL_ControlWrite(Tuner, RFA_CEIL, 13) ; + if (Tuner->IF_OUT <= 6280000UL) // Low IF + status += MXL_ControlWrite(Tuner, BB_IQSWAP, 0) ; + else // High IF + status += MXL_ControlWrite(Tuner, BB_IQSWAP, 1) ; + + } + if (Tuner->Mod_Type == MXL_ATSC) // ATSC Mode + { + Tuner->AGC_Mode = 1 ; // Single AGC Mode + + // Enable RSSI + status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; + status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; + status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 1) ; + status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; + // RSSI reference point + status += MXL_ControlWrite(Tuner, RFA_RSSI_REF, 2) ; + status += MXL_ControlWrite(Tuner, RFA_RSSI_REFH, 4) ; + status += MXL_ControlWrite(Tuner, RFA_RSSI_REFL, 1) ; + // TOP point + status += MXL_ControlWrite(Tuner, RFA_FLR, 2) ; + status += MXL_ControlWrite(Tuner, RFA_CEIL, 13) ; + + status += MXL_ControlWrite(Tuner, BB_INITSTATE_DLPF_TUNE, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, 5) ; // Low Zero + if (Tuner->IF_OUT <= 6280000UL) // Low IF + status += MXL_ControlWrite(Tuner, BB_IQSWAP, 0) ; + else // High IF + status += MXL_ControlWrite(Tuner, BB_IQSWAP, 1) ; + } + if (Tuner->Mod_Type == MXL_QAM) // QAM Mode + { + Tuner->Mode = MXL_DIGITAL_MODE; + + //Tuner->AGC_Mode = 1 ; // Single AGC Mode + + // Disable RSSI //change here for v2.6.5 + status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; + status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; + status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 0) ; + status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; + + // RSSI reference point + status += MXL_ControlWrite(Tuner, RFA_RSSI_REFH, 5) ; + status += MXL_ControlWrite(Tuner, RFA_RSSI_REF, 3) ; + status += MXL_ControlWrite(Tuner, RFA_RSSI_REFL, 2) ; + + status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, 3) ; //change here for v2.6.5 + + if (Tuner->IF_OUT <= 6280000UL) // Low IF + status += MXL_ControlWrite(Tuner, BB_IQSWAP, 0) ; + else // High IF + status += MXL_ControlWrite(Tuner, BB_IQSWAP, 1) ; + } + if (Tuner->Mod_Type == MXL_ANALOG_CABLE) // Analog Cable Mode + { + //Tuner->Mode = MXL_DIGITAL_MODE ; + Tuner->AGC_Mode = 1 ; // Single AGC Mode + + // Disable RSSI + status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; + status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; + status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 0) ; + status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; + + status += MXL_ControlWrite(Tuner, AGC_IF, 1) ; //change for 2.6.3 + status += MXL_ControlWrite(Tuner, AGC_RF, 15) ; + + status += MXL_ControlWrite(Tuner, BB_IQSWAP, 1) ; + } + + if (Tuner->Mod_Type == MXL_ANALOG_OTA) //Analog OTA Terrestrial mode add for 2.6.7 + { + //Tuner->Mode = MXL_ANALOG_MODE; + + // Enable RSSI + status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; + status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; + status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 1) ; + status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; + + // RSSI reference point + status += MXL_ControlWrite(Tuner, RFA_RSSI_REFH, 5) ; + status += MXL_ControlWrite(Tuner, RFA_RSSI_REF, 3) ; + status += MXL_ControlWrite(Tuner, RFA_RSSI_REFL, 2) ; + + status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, 3) ; + + status += MXL_ControlWrite(Tuner, BB_IQSWAP, 1) ; + } + + // RSSI disable + if(Tuner->EN_RSSI==0) + { + status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; + status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; + status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 0) ; + status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; + } + + return status ; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL_IFSynthInit // +// // +// Description: Tuner IF Synthesizer related register initialization // +// // +// Globals: // +// NONE // +// // +// Functions used: // +// Tuner_struct: structure defined at higher level // +// // +// Inputs: // +// Tuner : Tuner structure defined at higher level // +// // +// Outputs: // +// Tuner // +// // +// Return: // +// 0 : Successful // +// > 0 : Failed // +// // +/////////////////////////////////////////////////////////////////////////////// +_u16 MXL_IFSynthInit( Tuner_struct * Tuner ) +{ + _u16 status = 0 ; + // Declare Local Variables + _u32 Fref = 0 ; + _u32 Kdbl, intModVal ; + _u32 fracModVal ; + Kdbl = 2 ; + + if (Tuner->Fxtal >= 12000000UL && Tuner->Fxtal <= 16000000UL) + Kdbl = 2 ; + if (Tuner->Fxtal > 16000000UL && Tuner->Fxtal <= 32000000UL) + Kdbl = 1 ; + + // + // IF Synthesizer Control + // + if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF mode + { + if (Tuner->IF_LO == 41000000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + Fref = 328000000UL ; + } + if (Tuner->IF_LO == 47000000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 376000000UL ; + } + if (Tuner->IF_LO == 54000000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x10) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + Fref = 324000000UL ; + } + if (Tuner->IF_LO == 60000000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x10) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 360000000UL ; + } + if (Tuner->IF_LO == 39250000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + Fref = 314000000UL ; + } + if (Tuner->IF_LO == 39650000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + Fref = 317200000UL ; + } + if (Tuner->IF_LO == 40150000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + Fref = 321200000UL ; + } + if (Tuner->IF_LO == 40650000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + Fref = 325200000UL ; + } + } + + if (Tuner->Mode || (Tuner->Mode == 0 && Tuner->IF_Mode == 0)) + { + if (Tuner->IF_LO == 57000000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x10) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 342000000UL ; + } + if (Tuner->IF_LO == 44000000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 352000000UL ; + } + if (Tuner->IF_LO == 43750000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 350000000UL ; + } + if (Tuner->IF_LO == 36650000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 366500000UL ; + } + if (Tuner->IF_LO == 36150000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 361500000UL ; + } + if (Tuner->IF_LO == 36000000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 360000000UL ; + } + if (Tuner->IF_LO == 35250000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 352500000UL ; + } + if (Tuner->IF_LO == 34750000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 347500000UL ; + } + if (Tuner->IF_LO == 6280000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x07) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 376800000UL ; + } + if (Tuner->IF_LO == 5000000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x09) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 360000000UL ; + } + if (Tuner->IF_LO == 4500000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x06) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 360000000UL ; + } + if (Tuner->IF_LO == 4570000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x06) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 365600000UL ; + } + if (Tuner->IF_LO == 4000000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x05) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 360000000UL ; + } + if (Tuner->IF_LO == 57400000UL) + { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x10) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 344400000UL ; + } + if (Tuner->IF_LO == 44400000UL) + { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 355200000UL ; + } + if (Tuner->IF_LO == 44150000UL) + { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 353200000UL ; + } + if (Tuner->IF_LO == 37050000UL) + { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 370500000UL ; + } + if (Tuner->IF_LO == 36550000UL) + { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 365500000UL ; + } + if (Tuner->IF_LO == 36125000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 361250000UL ; + } + if (Tuner->IF_LO == 6000000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x07) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 360000000UL ; + } + if (Tuner->IF_LO == 5400000UL) + { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x07) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + Fref = 324000000UL ; + } + if (Tuner->IF_LO == 5380000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x07) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + Fref = 322800000UL ; + } + if (Tuner->IF_LO == 5200000UL) { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x09) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 374400000UL ; + } + if (Tuner->IF_LO == 4900000UL) + { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x09) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 352800000UL ; + } + if (Tuner->IF_LO == 4400000UL) + { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x06) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 352000000UL ; + } + if (Tuner->IF_LO == 4063000UL) //add for 2.6.8 + { + status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x05) ; + status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + Fref = 365670000UL ; + } + } + // CHCAL_INT_MOD_IF + // CHCAL_FRAC_MOD_IF + intModVal = Fref / (Tuner->Fxtal * Kdbl/2) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_IF, intModVal ) ; + + fracModVal = (2<<15)*(Fref/1000 - (Tuner->Fxtal/1000 * Kdbl/2) * intModVal); + fracModVal = fracModVal / ((Tuner->Fxtal * Kdbl/2)/1000) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_IF, fracModVal) ; + + + + return status ; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL_GetXtalInt // +// // +// Description: return the Crystal Integration Value for // +// TG_VCO_BIAS calculation // +// // +// Globals: // +// NONE // +// // +// Functions used: // +// NONE // +// // +// Inputs: // +// Crystal Frequency Value in Hz // +// // +// Outputs: // +// Calculated Crystal Frequency Integration Value // +// // +// Return: // +// 0 : Successful // +// > 0 : Failed // +// // +/////////////////////////////////////////////////////////////////////////////// +_u32 MXL_GetXtalInt(_u32 Xtal_Freq) +{ + if ((Xtal_Freq % 1000000) == 0) + return (Xtal_Freq / 10000) ; + else + return (((Xtal_Freq / 1000000) + 1)*100) ; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL5005_TuneRF // +// // +// Description: Set control names to tune to requested RF_IN frequency // +// // +// Globals: // +// None // +// // +// Functions used: // +// MXL_SynthRFTGLO_Calc // +// MXL5005_ControlWrite // +// MXL_GetXtalInt // +// // +// Inputs: // +// Tuner : Tuner structure defined at higher level // +// // +// Outputs: // +// Tuner // +// // +// Return: // +// 0 : Successful // +// 1 : Unsuccessful // +/////////////////////////////////////////////////////////////////////////////// +_u16 MXL_TuneRF(Tuner_struct *Tuner, _u32 RF_Freq) +{ + // Declare Local Variables + _u16 status = 0 ; + _u32 divider_val, E3, E4, E5, E5A ; + _u32 Fmax, Fmin, FmaxBin, FminBin ; + _u32 Kdbl_RF = 2; + _u32 tg_divval ; + _u32 tg_lo ; + _u32 Xtal_Int ; + + _u32 Fref_TG; + _u32 Fvco; +// _u32 temp; + + + Xtal_Int = MXL_GetXtalInt(Tuner->Fxtal ) ; + + Tuner->RF_IN = RF_Freq ; + + MXL_SynthRFTGLO_Calc( Tuner ) ; + + if (Tuner->Fxtal >= 12000000UL && Tuner->Fxtal <= 22000000UL) + Kdbl_RF = 2 ; + if (Tuner->Fxtal > 22000000 && Tuner->Fxtal <= 32000000) + Kdbl_RF = 1 ; + + // + // Downconverter Controls + // + // Look-Up Table Implementation for: + // DN_POLY + // DN_RFGAIN + // DN_CAP_RFLPF + // DN_EN_VHFUHFBAR + // DN_GAIN_ADJUST + // Change the boundary reference from RF_IN to RF_LO + if (Tuner->RF_LO < 40000000UL) { + return -1; + } + if (Tuner->RF_LO >= 40000000UL && Tuner->RF_LO <= 75000000UL) { + // Look-Up Table implementation + status += MXL_ControlWrite(Tuner, DN_POLY, 2) ; + status += MXL_ControlWrite(Tuner, DN_RFGAIN, 3) ; + status += MXL_ControlWrite(Tuner, DN_CAP_RFLPF, 423) ; + status += MXL_ControlWrite(Tuner, DN_EN_VHFUHFBAR, 1) ; + status += MXL_ControlWrite(Tuner, DN_GAIN_ADJUST, 1) ; + } + if (Tuner->RF_LO > 75000000UL && Tuner->RF_LO <= 100000000UL) { + // Look-Up Table implementation + status += MXL_ControlWrite(Tuner, DN_POLY, 3) ; + status += MXL_ControlWrite(Tuner, DN_RFGAIN, 3) ; + status += MXL_ControlWrite(Tuner, DN_CAP_RFLPF, 222) ; + status += MXL_ControlWrite(Tuner, DN_EN_VHFUHFBAR, 1) ; + status += MXL_ControlWrite(Tuner, DN_GAIN_ADJUST, 1) ; + } + if (Tuner->RF_LO > 100000000UL && Tuner->RF_LO <= 150000000UL) { + // Look-Up Table implementation + status += MXL_ControlWrite(Tuner, DN_POLY, 3) ; + status += MXL_ControlWrite(Tuner, DN_RFGAIN, 3) ; + status += MXL_ControlWrite(Tuner, DN_CAP_RFLPF, 147) ; + status += MXL_ControlWrite(Tuner, DN_EN_VHFUHFBAR, 1) ; + status += MXL_ControlWrite(Tuner, DN_GAIN_ADJUST, 2) ; + } + if (Tuner->RF_LO > 150000000UL && Tuner->RF_LO <= 200000000UL) { + // Look-Up Table implementation + status += MXL_ControlWrite(Tuner, DN_POLY, 3) ; + status += MXL_ControlWrite(Tuner, DN_RFGAIN, 3) ; + status += MXL_ControlWrite(Tuner, DN_CAP_RFLPF, 9) ; + status += MXL_ControlWrite(Tuner, DN_EN_VHFUHFBAR, 1) ; + status += MXL_ControlWrite(Tuner, DN_GAIN_ADJUST, 2) ; + } + if (Tuner->RF_LO > 200000000UL && Tuner->RF_LO <= 300000000UL) { + // Look-Up Table implementation + status += MXL_ControlWrite(Tuner, DN_POLY, 3) ; + status += MXL_ControlWrite(Tuner, DN_RFGAIN, 3) ; + status += MXL_ControlWrite(Tuner, DN_CAP_RFLPF, 0) ; + status += MXL_ControlWrite(Tuner, DN_EN_VHFUHFBAR, 1) ; + status += MXL_ControlWrite(Tuner, DN_GAIN_ADJUST, 3) ; + } + if (Tuner->RF_LO > 300000000UL && Tuner->RF_LO <= 650000000UL) { + // Look-Up Table implementation + status += MXL_ControlWrite(Tuner, DN_POLY, 3) ; + status += MXL_ControlWrite(Tuner, DN_RFGAIN, 1) ; + status += MXL_ControlWrite(Tuner, DN_CAP_RFLPF, 0) ; + status += MXL_ControlWrite(Tuner, DN_EN_VHFUHFBAR, 0) ; + status += MXL_ControlWrite(Tuner, DN_GAIN_ADJUST, 3) ; + } + if (Tuner->RF_LO > 650000000UL && Tuner->RF_LO <= 900000000UL) { + // Look-Up Table implementation + status += MXL_ControlWrite(Tuner, DN_POLY, 3) ; + status += MXL_ControlWrite(Tuner, DN_RFGAIN, 2) ; + status += MXL_ControlWrite(Tuner, DN_CAP_RFLPF, 0) ; + status += MXL_ControlWrite(Tuner, DN_EN_VHFUHFBAR, 0) ; + status += MXL_ControlWrite(Tuner, DN_GAIN_ADJUST, 3) ; + } + if (Tuner->RF_LO > 900000000UL) { + return -1; + } + // DN_IQTNBUF_AMP + // DN_IQTNGNBFBIAS_BST + if (Tuner->RF_LO >= 40000000UL && Tuner->RF_LO <= 75000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + } + if (Tuner->RF_LO > 75000000UL && Tuner->RF_LO <= 100000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + } + if (Tuner->RF_LO > 100000000UL && Tuner->RF_LO <= 150000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + } + if (Tuner->RF_LO > 150000000UL && Tuner->RF_LO <= 200000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + } + if (Tuner->RF_LO > 200000000UL && Tuner->RF_LO <= 300000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + } + if (Tuner->RF_LO > 300000000UL && Tuner->RF_LO <= 400000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + } + if (Tuner->RF_LO > 400000000UL && Tuner->RF_LO <= 450000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + } + if (Tuner->RF_LO > 450000000UL && Tuner->RF_LO <= 500000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + } + if (Tuner->RF_LO > 500000000UL && Tuner->RF_LO <= 550000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + } + if (Tuner->RF_LO > 550000000UL && Tuner->RF_LO <= 600000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + } + if (Tuner->RF_LO > 600000000UL && Tuner->RF_LO <= 650000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + } + if (Tuner->RF_LO > 650000000UL && Tuner->RF_LO <= 700000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + } + if (Tuner->RF_LO > 700000000UL && Tuner->RF_LO <= 750000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + } + if (Tuner->RF_LO > 750000000UL && Tuner->RF_LO <= 800000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + } + if (Tuner->RF_LO > 800000000UL && Tuner->RF_LO <= 850000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 10) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 1) ; + } + if (Tuner->RF_LO > 850000000UL && Tuner->RF_LO <= 900000000UL) { + status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 10) ; + status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 1) ; + } + + // + // Set RF Synth and LO Path Control + // + // Look-Up table implementation for: + // RFSYN_EN_OUTMUX + // RFSYN_SEL_VCO_OUT + // RFSYN_SEL_VCO_HI + // RFSYN_SEL_DIVM + // RFSYN_RF_DIV_BIAS + // DN_SEL_FREQ + // + // Set divider_val, Fmax, Fmix to use in Equations + FminBin = 28000000UL ; + FmaxBin = 42500000UL ; + if (Tuner->RF_LO >= 40000000UL && Tuner->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 1) ; + divider_val = 64 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 42500000UL ; + FmaxBin = 56000000UL ; + if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 1) ; + divider_val = 64 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 56000000UL ; + FmaxBin = 85000000UL ; + if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 1) ; + divider_val = 32 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 85000000UL ; + FmaxBin = 112000000UL ; + if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 1) ; + divider_val = 32 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 112000000UL ; + FmaxBin = 170000000UL ; + if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 2) ; + divider_val = 16 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 170000000UL ; + FmaxBin = 225000000UL ; + if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 2) ; + divider_val = 16 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 225000000UL ; + FmaxBin = 300000000UL ; + if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 4) ; + divider_val = 8 ; + Fmax = 340000000UL ; + Fmin = FminBin ; + } + FminBin = 300000000UL ; + FmaxBin = 340000000UL ; + if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0) ; + divider_val = 8 ; + Fmax = FmaxBin ; + Fmin = 225000000UL ; + } + FminBin = 340000000UL ; + FmaxBin = 450000000UL ; + if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 2) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0) ; + divider_val = 8 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 450000000UL ; + FmaxBin = 680000000UL ; + if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0) ; + divider_val = 4 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 680000000UL ; + FmaxBin = 900000000UL ; + if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0) ; + divider_val = 4 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + + // CHCAL_INT_MOD_RF + // CHCAL_FRAC_MOD_RF + // RFSYN_LPF_R + // CHCAL_EN_INT_RF + + // Equation E3 + // RFSYN_VCO_BIAS + E3 = (((Fmax-Tuner->RF_LO)/1000)*32)/((Fmax-Fmin)/1000) + 8 ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, E3) ; + + // Equation E4 + // CHCAL_INT_MOD_RF + E4 = (Tuner->RF_LO*divider_val/1000)/(2*Tuner->Fxtal*Kdbl_RF/1000) ; + MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, E4) ; + + // Equation E5 + // CHCAL_FRAC_MOD_RF + // CHCAL_EN_INT_RF + E5 = ((2<<17)*(Tuner->RF_LO/10000*divider_val - (E4*(2*Tuner->Fxtal*Kdbl_RF)/10000)))/(2*Tuner->Fxtal*Kdbl_RF/10000) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, E5) ; + + // Equation E5A + // RFSYN_LPF_R + E5A = (((Fmax - Tuner->RF_LO)/1000)*4/((Fmax-Fmin)/1000)) + 1 ; + status += MXL_ControlWrite(Tuner, RFSYN_LPF_R, E5A) ; + + // Euqation E5B + // CHCAL_EN_INIT_RF + status += MXL_ControlWrite(Tuner, CHCAL_EN_INT_RF, ((E5 == 0) ? 1 : 0)); + //if (E5 == 0) + // status += MXL_ControlWrite(Tuner, CHCAL_EN_INT_RF, 1); + //else + // status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, E5) ; + + // + // Set TG Synth + // + // Look-Up table implementation for: + // TG_LO_DIVVAL + // TG_LO_SELVAL + // + // Set divider_val, Fmax, Fmix to use in Equations + if (Tuner->TG_LO < 33000000UL) { + return -1; + } + FminBin = 33000000UL ; + FmaxBin = 50000000UL ; + if (Tuner->TG_LO >= FminBin && Tuner->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x6) ; + status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x0) ; + divider_val = 36 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 50000000UL ; + FmaxBin = 67000000UL ; + if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x1) ; + status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x0) ; + divider_val = 24 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 67000000UL ; + FmaxBin = 100000000UL ; + if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0xC) ; + status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x2) ; + divider_val = 18 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 100000000UL ; + FmaxBin = 150000000UL ; + if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x8) ; + status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x2) ; + divider_val = 12 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 150000000UL ; + FmaxBin = 200000000UL ; + if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x0) ; + status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x2) ; + divider_val = 8 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 200000000UL ; + FmaxBin = 300000000UL ; + if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x8) ; + status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x3) ; + divider_val = 6 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 300000000UL ; + FmaxBin = 400000000UL ; + if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x0) ; + status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x3) ; + divider_val = 4 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 400000000UL ; + FmaxBin = 600000000UL ; + if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x8) ; + status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x7) ; + divider_val = 3 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + FminBin = 600000000UL ; + FmaxBin = 900000000UL ; + if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x0) ; + status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x7) ; + divider_val = 2 ; + Fmax = FmaxBin ; + Fmin = FminBin ; + } + + // TG_DIV_VAL + tg_divval = (Tuner->TG_LO*divider_val/100000) + *(MXL_Ceiling(Tuner->Fxtal,1000000) * 100) / (Tuner->Fxtal/1000) ; + status += MXL_ControlWrite(Tuner, TG_DIV_VAL, tg_divval) ; + + if (Tuner->TG_LO > 600000000UL) + status += MXL_ControlWrite(Tuner, TG_DIV_VAL, tg_divval + 1 ) ; + + Fmax = 1800000000UL ; + Fmin = 1200000000UL ; + + + + // to prevent overflow of 32 bit unsigned integer, use following equation. Edit for v2.6.4 + Fref_TG = (Tuner->Fxtal/1000)/ MXL_Ceiling(Tuner->Fxtal, 1000000) ; // Fref_TF = Fref_TG*1000 + + Fvco = (Tuner->TG_LO/10000) * divider_val * Fref_TG; //Fvco = Fvco/10 + + tg_lo = (((Fmax/10 - Fvco)/100)*32) / ((Fmax-Fmin)/1000)+8; + + //below equation is same as above but much harder to debug. + //tg_lo = ( ((Fmax/10000 * Xtal_Int)/100) - ((Tuner->TG_LO/10000)*divider_val*(Tuner->Fxtal/10000)/100) )*32/((Fmax-Fmin)/10000 * Xtal_Int/100) + 8 ; + + + status += MXL_ControlWrite(Tuner, TG_VCO_BIAS , tg_lo) ; + + + + //add for 2.6.5 + //Special setting for QAM + if(Tuner ->Mod_Type == MXL_QAM) + { + if(Tuner->RF_IN < 680000000) + status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, 3) ; + else + status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, 2) ; + } + + + //remove 20.48MHz setting for 2.6.10 + + // + // Off Chip Tracking Filter Control + // + if (Tuner->TF_Type == MXL_TF_OFF) // Tracking Filter Off State; turn off all the banks + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; + + status += MXL_SetGPIO(Tuner, 3, 1) ; // turn off Bank 1 + status += MXL_SetGPIO(Tuner, 1, 1) ; // turn off Bank 2 + status += MXL_SetGPIO(Tuner, 4, 1) ; // turn off Bank 3 + } + + if (Tuner->TF_Type == MXL_TF_C) // Tracking Filter type C + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; + status += MXL_ControlWrite(Tuner, DAC_DIN_A, 0) ; + + if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 150000000) + { + + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 150000000 && Tuner->RF_IN < 280000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 280000000 && Tuner->RF_IN < 360000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 360000000 && Tuner->RF_IN < 560000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 560000000 && Tuner->RF_IN < 580000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 29) ; + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 580000000 && Tuner->RF_IN < 630000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 630000000 && Tuner->RF_IN < 700000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 16) ; + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 700000000 && Tuner->RF_IN < 760000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 7) ; + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 760000000 && Tuner->RF_IN <= 900000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank3 Off + } + } + + if (Tuner->TF_Type == MXL_TF_C_H) // Tracking Filter type C-H for Hauppauge only + { + status += MXL_ControlWrite(Tuner, DAC_DIN_A, 0) ; + + if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 150000000) + { + + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 150000000 && Tuner->RF_IN < 280000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 280000000 && Tuner->RF_IN < 360000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 360000000 && Tuner->RF_IN < 560000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 560000000 && Tuner->RF_IN < 580000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 580000000 && Tuner->RF_IN < 630000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 630000000 && Tuner->RF_IN < 700000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 700000000 && Tuner->RF_IN < 760000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 760000000 && Tuner->RF_IN <= 900000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank3 Off + } + } + + if (Tuner->TF_Type == MXL_TF_D) // Tracking Filter type D + { + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + + if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 174000000) + { + + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 174000000 && Tuner->RF_IN < 250000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 250000000 && Tuner->RF_IN < 310000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 310000000 && Tuner->RF_IN < 360000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 360000000 && Tuner->RF_IN < 470000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 470000000 && Tuner->RF_IN < 640000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 640000000 && Tuner->RF_IN <= 900000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + } + + + if (Tuner->TF_Type == MXL_TF_D_L) // Tracking Filter type D-L for Lumanate ONLY change for 2.6.3 + { + status += MXL_ControlWrite(Tuner, DAC_DIN_A, 0) ; + + if (Tuner->RF_IN >= 471000000 && (Tuner->RF_IN - 471000000)%6000000 != 0) // if UHF and terrestrial => Turn off Tracking Filter + { + // Turn off all the banks + status += MXL_SetGPIO(Tuner, 3, 1) ; + status += MXL_SetGPIO(Tuner, 1, 1) ; + status += MXL_SetGPIO(Tuner, 4, 1) ; + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; + + status += MXL_ControlWrite(Tuner, AGC_IF, 10) ; + } + + else // if VHF or cable => Turn on Tracking Filter + { + if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 140000000) + { + + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 Off + } + if (Tuner->RF_IN >= 140000000 && Tuner->RF_IN < 240000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 Off + } + if (Tuner->RF_IN >= 240000000 && Tuner->RF_IN < 340000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 Off + } + if (Tuner->RF_IN >= 340000000 && Tuner->RF_IN < 430000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 On + } + if (Tuner->RF_IN >= 430000000 && Tuner->RF_IN < 470000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 On + } + if (Tuner->RF_IN >= 470000000 && Tuner->RF_IN < 570000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 On + } + if (Tuner->RF_IN >= 570000000 && Tuner->RF_IN < 620000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Offq + } + if (Tuner->RF_IN >= 620000000 && Tuner->RF_IN < 760000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 760000000 && Tuner->RF_IN <= 900000000) + { + status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + } + } + + if (Tuner->TF_Type == MXL_TF_E) // Tracking Filter type E + { + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + + if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 174000000) + { + + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 174000000 && Tuner->RF_IN < 250000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 250000000 && Tuner->RF_IN < 310000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 310000000 && Tuner->RF_IN < 360000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 360000000 && Tuner->RF_IN < 470000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 470000000 && Tuner->RF_IN < 640000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 640000000 && Tuner->RF_IN <= 900000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + } + + if (Tuner->TF_Type == MXL_TF_F) // Tracking Filter type F + { + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + + if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 160000000) + { + + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 160000000 && Tuner->RF_IN < 210000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 210000000 && Tuner->RF_IN < 300000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 300000000 && Tuner->RF_IN < 390000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 390000000 && Tuner->RF_IN < 515000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 515000000 && Tuner->RF_IN < 650000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 650000000 && Tuner->RF_IN <= 900000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + } + + if (Tuner->TF_Type == MXL_TF_E_2) // Tracking Filter type E_2 + { + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + + if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 174000000) + { + + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 174000000 && Tuner->RF_IN < 250000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 250000000 && Tuner->RF_IN < 350000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 350000000 && Tuner->RF_IN < 400000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 400000000 && Tuner->RF_IN < 570000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 570000000 && Tuner->RF_IN < 770000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 770000000 && Tuner->RF_IN <= 900000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + } + + if (Tuner->TF_Type == MXL_TF_G) // Tracking Filter type G add for v2.6.8 + { + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + + if (Tuner->RF_IN >= 50000000 && Tuner->RF_IN < 190000000) + { + + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 190000000 && Tuner->RF_IN < 280000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 280000000 && Tuner->RF_IN < 350000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 350000000 && Tuner->RF_IN < 400000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 400000000 && Tuner->RF_IN < 470000000) //modified for 2.6.11 + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 470000000 && Tuner->RF_IN < 640000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 640000000 && Tuner->RF_IN < 820000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 820000000 && Tuner->RF_IN <= 900000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + } + + if (Tuner->TF_Type == MXL_TF_E_NA) // Tracking Filter type E-NA for Empia ONLY change for 2.6.8 + { + status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + + if (Tuner->RF_IN >= 471000000 && (Tuner->RF_IN - 471000000)%6000000 != 0) //if UHF and terrestrial=> Turn off Tracking Filter + { + // Turn off all the banks + status += MXL_SetGPIO(Tuner, 3, 1) ; + status += MXL_SetGPIO(Tuner, 1, 1) ; + status += MXL_SetGPIO(Tuner, 4, 1) ; + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; + + //2.6.12 + //Turn on RSSI + status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; + status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; + status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 1) ; + status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; + + // RSSI reference point + status += MXL_ControlWrite(Tuner, RFA_RSSI_REFH, 5) ; + status += MXL_ControlWrite(Tuner, RFA_RSSI_REF, 3) ; + status += MXL_ControlWrite(Tuner, RFA_RSSI_REFL, 2) ; + + + //status += MXL_ControlWrite(Tuner, AGC_IF, 10) ; //doesn't matter since RSSI is turn on + + //following parameter is from analog OTA mode, can be change to seek better performance + status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, 3) ; + } + + else //if VHF or Cable => Turn on Tracking Filter + { + //2.6.12 + //Turn off RSSI + status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 0) ; + + //change back from above condition + status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, 5) ; + + + if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 174000000) + { + + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 174000000 && Tuner->RF_IN < 250000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 250000000 && Tuner->RF_IN < 350000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + if (Tuner->RF_IN >= 350000000 && Tuner->RF_IN < 400000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 400000000 && Tuner->RF_IN < 570000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 570000000 && Tuner->RF_IN < 770000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + } + if (Tuner->RF_IN >= 770000000 && Tuner->RF_IN <= 900000000) + { + status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + } + } + } + return status ; +} + +_u16 MXL_SetGPIO(Tuner_struct *Tuner, _u8 GPIO_Num, _u8 GPIO_Val) +{ + _u16 status = 0 ; + + if (GPIO_Num == 1) + status += MXL_ControlWrite(Tuner, GPIO_1B, GPIO_Val ? 0 : 1) ; + // GPIO2 is not available + if (GPIO_Num == 3) + { + if (GPIO_Val == 1) { + status += MXL_ControlWrite(Tuner, GPIO_3, 0) ; + status += MXL_ControlWrite(Tuner, GPIO_3B, 0) ; + } + if (GPIO_Val == 0) { + status += MXL_ControlWrite(Tuner, GPIO_3, 1) ; + status += MXL_ControlWrite(Tuner, GPIO_3B, 1) ; + } + if (GPIO_Val == 3) { // tri-state + status += MXL_ControlWrite(Tuner, GPIO_3, 0) ; + status += MXL_ControlWrite(Tuner, GPIO_3B, 1) ; + } + } + if (GPIO_Num == 4) + { + if (GPIO_Val == 1) { + status += MXL_ControlWrite(Tuner, GPIO_4, 0) ; + status += MXL_ControlWrite(Tuner, GPIO_4B, 0) ; + } + if (GPIO_Val == 0) { + status += MXL_ControlWrite(Tuner, GPIO_4, 1) ; + status += MXL_ControlWrite(Tuner, GPIO_4B, 1) ; + } + if (GPIO_Val == 3) { // tri-state + status += MXL_ControlWrite(Tuner, GPIO_4, 0) ; + status += MXL_ControlWrite(Tuner, GPIO_4B, 1) ; + } + } + + return status ; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL_ControlWrite // +// // +// Description: Update control name value // +// // +// Globals: // +// NONE // +// // +// Functions used: // +// MXL_ControlWrite( Tuner, controlName, value, Group ) // +// // +// Inputs: // +// Tuner : Tuner structure // +// ControlName : Control name to be updated // +// value : Value to be written // +// // +// Outputs: // +// Tuner : Tuner structure defined at higher level // +// // +// Return: // +// 0 : Successful write // +// >0 : Value exceed maximum allowed for control number // +// // +/////////////////////////////////////////////////////////////////////////////// +_u16 MXL_ControlWrite(Tuner_struct *Tuner, _u16 ControlNum, _u32 value) +{ + _u16 status = 0 ; + // Will write ALL Matching Control Name + status += MXL_ControlWrite_Group( Tuner, ControlNum, value, 1 ) ; // Write Matching INIT Control + status += MXL_ControlWrite_Group( Tuner, ControlNum, value, 2 ) ; // Write Matching CH Control +#ifdef _MXL_INTERNAL + status += MXL_ControlWrite_Group( Tuner, ControlNum, value, 3 ) ; // Write Matching MXL Control +#endif + + return status ; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL_ControlWrite // +// // +// Description: Update control name value // +// // +// Globals: // +// NONE // +// // +// Functions used: // +// strcmp // +// // +// Inputs: // +// Tuner_struct: structure defined at higher level // +// ControlName : Control Name // +// value : Value Assigned to Control Name // +// controlGroup : Control Register Group // +// // +// Outputs: // +// NONE // +// // +// Return: // +// 0 : Successful write // +// 1 : Value exceed maximum allowed for control name // +// 2 : Control name not found // +// // +/////////////////////////////////////////////////////////////////////////////// +_u16 MXL_ControlWrite_Group(Tuner_struct *Tuner, _u16 controlNum, _u32 value, _u16 controlGroup) +{ + _u16 i, j, k ; + _u32 highLimit ; + _u32 ctrlVal ; + + if( controlGroup == 1) // Initial Control + { + for (i=0; iInit_Ctrl_Num ; i++) + { + if ( controlNum == Tuner->Init_Ctrl[i].Ctrl_Num ) + { // find the control Name + highLimit = 1 << Tuner->Init_Ctrl[i].size ; + if ( value < highLimit) + { + for( j=0; jInit_Ctrl[i].size; j++) + { + Tuner->Init_Ctrl[i].val[j] = (_u8)((value >> j) & 0x01) ; + // change the register map accordingly + MXL_RegWriteBit( Tuner, (_u8)(Tuner->Init_Ctrl[i].addr[j]), + (_u8)(Tuner->Init_Ctrl[i].bit[j]), + (_u8)((value>>j) & 0x01) ) ; + } + ctrlVal = 0 ; + for(k=0; kInit_Ctrl[i].size; k++) + { + ctrlVal += Tuner->Init_Ctrl[i].val[k] * (1 << k) ; + } + } + else + { + return -1 ; + } + } + } + } + if ( controlGroup == 2) // Chan change Control + { + for (i=0; iCH_Ctrl_Num; i++) + { + if ( controlNum == Tuner->CH_Ctrl[i].Ctrl_Num ) + { // find the control Name + highLimit = 1 << Tuner->CH_Ctrl[i].size ; + if ( value < highLimit) + { + for( j=0; jCH_Ctrl[i].size; j++) + { + Tuner->CH_Ctrl[i].val[j] = (_u8)((value >> j) & 0x01) ; + // change the register map accordingly + MXL_RegWriteBit( Tuner, (_u8)(Tuner->CH_Ctrl[i].addr[j]), + (_u8)(Tuner->CH_Ctrl[i].bit[j]), + (_u8)((value>>j) & 0x01) ) ; + } + ctrlVal = 0 ; + for(k=0; kCH_Ctrl[i].size; k++) + { + ctrlVal += Tuner->CH_Ctrl[i].val[k] * (1 << k) ; + } + } + else + { + return -1 ; + } + } + } + } +#ifdef _MXL_INTERNAL + if ( controlGroup == 3) // Maxlinear Control + { + for (i=0; iMXL_Ctrl_Num; i++) + { + if ( controlNum == Tuner->MXL_Ctrl[i].Ctrl_Num ) + { // find the control Name + highLimit = (1 << Tuner->MXL_Ctrl[i].size) ; + if ( value < highLimit) + { + for( j=0; jMXL_Ctrl[i].size; j++) + { + Tuner->MXL_Ctrl[i].val[j] = (_u8)((value >> j) & 0x01) ; + // change the register map accordingly + MXL_RegWriteBit( Tuner, (_u8)(Tuner->MXL_Ctrl[i].addr[j]), + (_u8)(Tuner->MXL_Ctrl[i].bit[j]), + (_u8)((value>>j) & 0x01) ) ; + } + ctrlVal = 0 ; + for(k=0; kMXL_Ctrl[i].size; k++) + { + ctrlVal += Tuner->MXL_Ctrl[i].val[k] * (1 << k) ; + } + } + else + { + return -1 ; + } + } + } + } +#endif + return 0 ; // successful return +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL_RegWrite // +// // +// Description: Update tuner register value // +// // +// Globals: // +// NONE // +// // +// Functions used: // +// NONE // +// // +// Inputs: // +// Tuner_struct: structure defined at higher level // +// RegNum : Register address to be assigned a value // +// RegVal : Register value to write // +// // +// Outputs: // +// NONE // +// // +// Return: // +// 0 : Successful write // +// -1 : Invalid Register Address // +// // +/////////////////////////////////////////////////////////////////////////////// +_u16 MXL_RegWrite(Tuner_struct *Tuner, _u8 RegNum, _u8 RegVal) +{ + int i ; + + for (i=0; i<104; i++) + { + if (RegNum == Tuner->TunerRegs[i].Reg_Num ) + { + Tuner->TunerRegs[i].Reg_Val = RegVal ; + return 0 ; + } + } + + return 1 ; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL_RegRead // +// // +// Description: Retrieve tuner register value // +// // +// Globals: // +// NONE // +// // +// Functions used: // +// NONE // +// // +// Inputs: // +// Tuner_struct: structure defined at higher level // +// RegNum : Register address to be assigned a value // +// // +// Outputs: // +// RegVal : Retrieved register value // +// // +// Return: // +// 0 : Successful read // +// -1 : Invalid Register Address // +// // +/////////////////////////////////////////////////////////////////////////////// +_u16 MXL_RegRead(Tuner_struct *Tuner, _u8 RegNum, _u8 *RegVal) +{ + int i ; + + for (i=0; i<104; i++) + { + if (RegNum == Tuner->TunerRegs[i].Reg_Num ) + { + *RegVal = (_u8)(Tuner->TunerRegs[i].Reg_Val) ; + return 0 ; + } + } + + return 1 ; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL_ControlRead // +// // +// Description: Retrieve the control value based on the control name // +// // +// Globals: // +// NONE // +// // +// Inputs: // +// Tuner_struct : structure defined at higher level // +// ControlName : Control Name // +// // +// Outputs: // +// value : returned control value // +// // +// Return: // +// 0 : Successful read // +// -1 : Invalid control name // +// // +/////////////////////////////////////////////////////////////////////////////// +_u16 MXL_ControlRead(Tuner_struct *Tuner, _u16 controlNum, _u32 * value) +{ + _u32 ctrlVal ; + _u16 i, k ; + + for (i=0; iInit_Ctrl_Num ; i++) + { + if ( controlNum == Tuner->Init_Ctrl[i].Ctrl_Num ) + { + ctrlVal = 0 ; + for(k=0; kInit_Ctrl[i].size; k++) + ctrlVal += Tuner->Init_Ctrl[i].val[k] * (1 << k) ; + *value = ctrlVal ; + return 0 ; + } + } + for (i=0; iCH_Ctrl_Num ; i++) + { + if ( controlNum == Tuner->CH_Ctrl[i].Ctrl_Num ) + { + ctrlVal = 0 ; + for(k=0; kCH_Ctrl[i].size; k++) + ctrlVal += Tuner->CH_Ctrl[i].val[k] * (1 << k) ; + *value = ctrlVal ; + return 0 ; + } + } + +#ifdef _MXL_INTERNAL + for (i=0; iMXL_Ctrl_Num ; i++) + { + if ( controlNum == Tuner->MXL_Ctrl[i].Ctrl_Num ) + { + ctrlVal = 0 ; + for(k=0; kMXL_Ctrl[i].size; k++) + ctrlVal += Tuner->MXL_Ctrl[i].val[k] * (1<Init_Ctrl_Num ; i++) + { + if ( controlNum == Tuner->Init_Ctrl[i].Ctrl_Num ) + { + Count = 1 ; + RegNum[0] = (_u8)(Tuner->Init_Ctrl[i].addr[0]) ; + + for(k=1; kInit_Ctrl[i].size; k++) + { + for (j= 0; jInit_Ctrl[i].addr[k] != RegNum[j]) + { + Count ++ ; + RegNum[Count-1] = (_u8)(Tuner->Init_Ctrl[i].addr[k]) ; + } + } + + } + *count = Count ; + return 0 ; + } + } + for (i=0; iCH_Ctrl_Num ; i++) + { + if ( controlNum == Tuner->CH_Ctrl[i].Ctrl_Num ) + { + Count = 1 ; + RegNum[0] = (_u8)(Tuner->CH_Ctrl[i].addr[0]) ; + + for(k=1; kCH_Ctrl[i].size; k++) + { + for (j= 0; jCH_Ctrl[i].addr[k] != RegNum[j]) + { + Count ++ ; + RegNum[Count-1] = (_u8)(Tuner->CH_Ctrl[i].addr[k]) ; + } + } + } + *count = Count ; + return 0 ; + } + } +#ifdef _MXL_INTERNAL + for (i=0; iMXL_Ctrl_Num ; i++) + { + if ( controlNum == Tuner->MXL_Ctrl[i].Ctrl_Num ) + { + Count = 1 ; + RegNum[0] = (_u8)(Tuner->MXL_Ctrl[i].addr[0]) ; + + for(k=1; kMXL_Ctrl[i].size; k++) + { + for (j= 0; jMXL_Ctrl[i].addr[k] != RegNum[j]) + { + Count ++ ; + RegNum[Count-1] = (_u8)Tuner->MXL_Ctrl[i].addr[k] ; + } + } + } + *count = Count ; + return 0 ; + } + } +#endif + *count = 0 ; + return 1 ; +} + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL_RegWriteBit // +// // +// Description: Write a register for specified register address, // +// register bit and register bit value // +// // +// Globals: // +// NONE // +// // +// Inputs: // +// Tuner_struct : structure defined at higher level // +// address : register address // +// bit : register bit number // +// bitVal : register bit value // +// // +// Outputs: // +// NONE // +// // +// Return: // +// NONE // +// // +/////////////////////////////////////////////////////////////////////////////// + +void MXL_RegWriteBit(Tuner_struct *Tuner, _u8 address, _u8 bit, _u8 bitVal) +{ + int i ; + + // Declare Local Constants + const _u8 AND_MAP[8] = { + 0xFE, 0xFD, 0xFB, 0xF7, + 0xEF, 0xDF, 0xBF, 0x7F } ; + + const _u8 OR_MAP[8] = { + 0x01, 0x02, 0x04, 0x08, + 0x10, 0x20, 0x40, 0x80 } ; + + for(i=0; iTunerRegs_Num; i++) { + if ( Tuner->TunerRegs[i].Reg_Num == address ) { + if (bitVal) + Tuner->TunerRegs[i].Reg_Val |= OR_MAP[bit] ; + else + Tuner->TunerRegs[i].Reg_Val &= AND_MAP[bit] ; + break ; + } + } +} ; + + +/////////////////////////////////////////////////////////////////////////////// +// // +// Function: MXL_Ceiling // +// // +// Description: Complete to closest increment of resolution // +// // +// Globals: // +// NONE // +// // +// Functions used: // +// NONE // +// // +// Inputs: // +// value : Input number to compute // +// resolution : Increment step // +// // +// Outputs: // +// NONE // +// // +// Return: // +// Computed value // +// // +/////////////////////////////////////////////////////////////////////////////// +_u32 MXL_Ceiling( _u32 value, _u32 resolution ) +{ + return (value/resolution + (value%resolution > 0 ? 1 : 0)) ; +}; + +// +// Retrieve the Initialzation Registers +// +_u16 MXL_GetInitRegister(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) +{ + _u16 status = 0; + int i ; + + _u8 RegAddr[] = {11, 12, 13, 22, 32, 43, 44, 53, 56, 59, 73, + 76, 77, 91, 134, 135, 137, 147, + 156, 166, 167, 168, 25 } ; + *count = sizeof(RegAddr) / sizeof(_u8) ; + + status += MXL_BlockInit(Tuner) ; + + for (i=0 ; i< *count; i++) + { + RegNum[i] = RegAddr[i] ; + status += MXL_RegRead(Tuner, RegNum[i], &RegVal[i]) ; + } + + return status ; +} + +_u16 MXL_GetCHRegister(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) +{ + _u16 status = 0; + int i ; + +//add 77, 166, 167, 168 register for 2.6.12 +#ifdef _MXL_PRODUCTION + _u8 RegAddr[] = {14, 15, 16, 17, 22, 43, 65, 68, 69, 70, 73, 92, 93, 106, + 107, 108, 109, 110, 111, 112, 136, 138, 149, 77, 166, 167, 168 } ; +#else + _u8 RegAddr[] = {14, 15, 16, 17, 22, 43, 68, 69, 70, 73, 92, 93, 106, + 107, 108, 109, 110, 111, 112, 136, 138, 149, 77, 166, 167, 168 } ; + //_u8 RegAddr[171]; + //for (i=0; i<=170; i++) + // RegAddr[i] = i; +#endif + + *count = sizeof(RegAddr) / sizeof(_u8) ; + + for (i=0 ; i< *count; i++) + { + RegNum[i] = RegAddr[i] ; + status += MXL_RegRead(Tuner, RegNum[i], &RegVal[i]) ; + } + + return status ; + +} + +_u16 MXL_GetCHRegister_ZeroIF(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) +{ + _u16 status = 0 ; + int i ; + + _u8 RegAddr[] = {43, 136} ; + + *count = sizeof(RegAddr) / sizeof(_u8) ; + + for (i=0; i<*count; i++) + { + RegNum[i] = RegAddr[i] ; + status += MXL_RegRead(Tuner, RegNum[i], &RegVal[i]) ; + } + return status ; + +} + +_u16 MXL_GetCHRegister_LowIF(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) +{ + _u16 status = 0 ; + int i ; + + _u8 RegAddr[] = {138} ; + + *count = sizeof(RegAddr) / sizeof(_u8) ; + + for (i=0; i<*count; i++) + { + RegNum[i] = RegAddr[i] ; + status += MXL_RegRead(Tuner, RegNum[i], &RegVal[i]) ; + } + return status ; + +} + +_u16 MXL_GetMasterControl(_u8 *MasterReg, int state) +{ + if (state == 1) // Load_Start + *MasterReg = 0xF3 ; + if (state == 2) // Power_Down + *MasterReg = 0x41 ; + if (state == 3) // Synth_Reset + *MasterReg = 0xB1 ; + if (state == 4) // Seq_Off + *MasterReg = 0xF1 ; + + return 0 ; +} + +#ifdef _MXL_PRODUCTION +_u16 MXL_VCORange_Test(Tuner_struct *Tuner, int VCO_Range) +{ + _u16 status = 0 ; + + if (VCO_Range == 1) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1 ) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0 ) ; + if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode + { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 56 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 180224 ) ; + } + if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode + { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 56 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 222822 ) ; + } + if (Tuner->Mode == 1) // Digital Mode + { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 56 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 229376 ) ; + } + } + + if (VCO_Range == 2) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1 ) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 41 ) ; + if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode + { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438 ) ; + } + if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode + { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438 ) ; + } + if (Tuner->Mode == 1) // Digital Mode + { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 41 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 16384 ) ; + } + } + + if (VCO_Range == 3) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1 ) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42 ) ; + if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode + { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 44 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 173670 ) ; + } + if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode + { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 44 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 173670 ) ; + } + if (Tuner->Mode == 1) // Digital Mode + { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 245760 ) ; + } + } + + if (VCO_Range == 4) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1) ; + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1 ) ; + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27 ) ; + if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode + { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438 ) ; + } + if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode + { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438 ) ; + } + if (Tuner->Mode == 1) // Digital Mode + { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 212992 ) ; + } + } + + return status ; +} + +_u16 MXL_Hystersis_Test(Tuner_struct *Tuner, int Hystersis) +{ + _u16 status = 0 ; + + if (Hystersis == 1) + status += MXL_ControlWrite(Tuner, DN_BYPASS_AGC_I2C, 1) ; + + return status ; +} +#endif + + + + + + + + + + + + + + + diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h new file mode 100644 index 0000000..8542fc1 --- /dev/null +++ b/drivers/media/common/tuners/mxl5005s.h @@ -0,0 +1,718 @@ +/* + * For the Realtek RTL chip RTL2831U + * Realtek Release Date: 2008-03-14, ver 080314 + * Realtek version RTL2831 Linux driver version 080314 + * ver 080314 + * + * for linux kernel version 2.6.21.4 - 2.6.22-14 + * support MXL5005s and MT2060 tuners (support tuner auto-detecting) + * support two IR types -- RC5 and NEC + * + * Known boards with Realtek RTL chip RTL2821U + * Freecom USB stick 14aa:0160 (version 4) + * Conceptronic CTVDIGRCU + * + * Copyright (c) 2008 Realtek + * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper + * This code is placed under the terms of the GNU General Public License + * + * Released by Realtek under GPLv2. + * Thanks to Realtek for a lot of support we received ! + * + * Revision: 080314 - original version + */ + + +#ifndef __TUNER_MXL5005S_H +#define __TUNER_MXL5005S_H + + + +// The following context is source code provided by MaxLinear. + + +// MaxLinear source code - Common.h + + + +//#pragma once + +typedef unsigned char _u8; // At least 1 Byte +typedef unsigned short _u16; // At least 2 Bytes +typedef signed short _s16; +typedef unsigned long _u32; // At least 4 Bytes +typedef void * HANDLE; // Pointer to memory location + +#define TUNER_REGS_NUM 104 +#define INITCTRL_NUM 40 +#ifdef _MXL_PRODUCTION +#define CHCTRL_NUM 39 +#else +#define CHCTRL_NUM 36 +#endif + +#define MXLCTRL_NUM 189 + +#define MASTER_CONTROL_ADDR 9 + + + + +// Enumeration of AGC Mode +typedef enum +{ + MXL_DUAL_AGC = 0 , + MXL_SINGLE_AGC +} AGC_Mode ; + +// +// Enumeration of Master Control Register State +// +typedef enum +{ + MC_LOAD_START = 1 , + MC_POWER_DOWN , + MC_SYNTH_RESET , + MC_SEQ_OFF +} Master_Control_State ; + +// +// Enumeration of MXL5005 Tuner Mode +// +typedef enum +{ + MXL_ANALOG_MODE = 0 , + MXL_DIGITAL_MODE + +} Tuner_Mode ; + +// +// Enumeration of MXL5005 Tuner IF Mode +// +typedef enum +{ + MXL_ZERO_IF = 0 , + MXL_LOW_IF + +} Tuner_IF_Mode ; + +// +// Enumeration of MXL5005 Tuner Clock Out Mode +// +typedef enum +{ + MXL_CLOCK_OUT_DISABLE = 0 , + MXL_CLOCK_OUT_ENABLE +} Tuner_Clock_Out ; + +// +// Enumeration of MXL5005 Tuner Div Out Mode +// +typedef enum +{ + MXL_DIV_OUT_1 = 0 , + MXL_DIV_OUT_4 + +} Tuner_Div_Out ; + +// +// Enumeration of MXL5005 Tuner Pull-up Cap Select Mode +// +typedef enum +{ + MXL_CAP_SEL_DISABLE = 0 , + MXL_CAP_SEL_ENABLE + +} Tuner_Cap_Select ; + +// +// Enumeration of MXL5005 Tuner RSSI Mode +// +typedef enum +{ + MXL_RSSI_DISABLE = 0 , + MXL_RSSI_ENABLE + +} Tuner_RSSI ; + +// +// Enumeration of MXL5005 Tuner Modulation Type +// +typedef enum +{ + MXL_DEFAULT_MODULATION = 0 , + MXL_DVBT, + MXL_ATSC, + MXL_QAM, + MXL_ANALOG_CABLE, + MXL_ANALOG_OTA + +} Tuner_Modu_Type ; + +// +// Enumeration of MXL5005 Tuner Tracking Filter Type +// +typedef enum +{ + MXL_TF_DEFAULT = 0 , + MXL_TF_OFF, + MXL_TF_C, + MXL_TF_C_H, + MXL_TF_D, + MXL_TF_D_L, + MXL_TF_E, + MXL_TF_F, + MXL_TF_E_2, + MXL_TF_E_NA, + MXL_TF_G + + +} Tuner_TF_Type ; + + +// +// MXL5005 Tuner Register Struct +// +typedef struct _TunerReg_struct +{ + _u16 Reg_Num ; // Tuner Register Address + _u16 Reg_Val ; // Current sofware programmed value waiting to be writen +} TunerReg_struct ; + +// +// MXL5005 Tuner Control Struct +// +typedef struct _TunerControl_struct { + _u16 Ctrl_Num ; // Control Number + _u16 size ; // Number of bits to represent Value + _u16 addr[25] ; // Array of Tuner Register Address for each bit position + _u16 bit[25] ; // Array of bit position in Register Address for each bit position + _u16 val[25] ; // Binary representation of Value +} TunerControl_struct ; + +// +// MXL5005 Tuner Struct +// +typedef struct _Tuner_struct +{ + _u8 Mode ; // 0: Analog Mode ; 1: Digital Mode + _u8 IF_Mode ; // for Analog Mode, 0: zero IF; 1: low IF + _u32 Chan_Bandwidth ; // filter channel bandwidth (6, 7, 8) + _u32 IF_OUT ; // Desired IF Out Frequency + _u16 IF_OUT_LOAD ; // IF Out Load Resistor (200/300 Ohms) + _u32 RF_IN ; // RF Input Frequency + _u32 Fxtal ; // XTAL Frequency + _u8 AGC_Mode ; // AGC Mode 0: Dual AGC; 1: Single AGC + _u16 TOP ; // Value: take over point + _u8 CLOCK_OUT ; // 0: turn off clock out; 1: turn on clock out + _u8 DIV_OUT ; // 4MHz or 16MHz + _u8 CAPSELECT ; // 0: disable On-Chip pulling cap; 1: enable + _u8 EN_RSSI ; // 0: disable RSSI; 1: enable RSSI + _u8 Mod_Type ; // Modulation Type; + // 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable + _u8 TF_Type ; // Tracking Filter Type + // 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H + + // Calculated Settings + _u32 RF_LO ; // Synth RF LO Frequency + _u32 IF_LO ; // Synth IF LO Frequency + _u32 TG_LO ; // Synth TG_LO Frequency + + // Pointers to ControlName Arrays + _u16 Init_Ctrl_Num ; // Number of INIT Control Names + TunerControl_struct Init_Ctrl[INITCTRL_NUM] ; // INIT Control Names Array Pointer + _u16 CH_Ctrl_Num ; // Number of CH Control Names + TunerControl_struct CH_Ctrl[CHCTRL_NUM] ; // CH Control Name Array Pointer + _u16 MXL_Ctrl_Num ; // Number of MXL Control Names + TunerControl_struct MXL_Ctrl[MXLCTRL_NUM] ; // MXL Control Name Array Pointer + + // Pointer to Tuner Register Array + _u16 TunerRegs_Num ; // Number of Tuner Registers + TunerReg_struct TunerRegs[TUNER_REGS_NUM] ; // Tuner Register Array Pointer +} Tuner_struct ; + + + +typedef enum +{ + // + // Initialization Control Names + // + DN_IQTN_AMP_CUT = 1 , // 1 + BB_MODE , // 2 + BB_BUF , // 3 + BB_BUF_OA , // 4 + BB_ALPF_BANDSELECT , // 5 + BB_IQSWAP , // 6 + BB_DLPF_BANDSEL , // 7 + RFSYN_CHP_GAIN , // 8 + RFSYN_EN_CHP_HIGAIN , // 9 + AGC_IF , // 10 + AGC_RF , // 11 + IF_DIVVAL , // 12 + IF_VCO_BIAS , // 13 + CHCAL_INT_MOD_IF , // 14 + CHCAL_FRAC_MOD_IF , // 15 + DRV_RES_SEL , // 16 + I_DRIVER , // 17 + EN_AAF , // 18 + EN_3P , // 19 + EN_AUX_3P , // 20 + SEL_AAF_BAND , // 21 + SEQ_ENCLK16_CLK_OUT , // 22 + SEQ_SEL4_16B , // 23 + XTAL_CAPSELECT , // 24 + IF_SEL_DBL , // 25 + RFSYN_R_DIV , // 26 + SEQ_EXTSYNTHCALIF , // 27 + SEQ_EXTDCCAL , // 28 + AGC_EN_RSSI , // 29 + RFA_ENCLKRFAGC , // 30 + RFA_RSSI_REFH , // 31 + RFA_RSSI_REF , // 32 + RFA_RSSI_REFL , // 33 + RFA_FLR , // 34 + RFA_CEIL , // 35 + SEQ_EXTIQFSMPULSE , // 36 + OVERRIDE_1 , // 37 + BB_INITSTATE_DLPF_TUNE, // 38 + TG_R_DIV, // 39 + EN_CHP_LIN_B , // 40 + + // + // Channel Change Control Names + // + DN_POLY = 51 , // 51 + DN_RFGAIN , // 52 + DN_CAP_RFLPF , // 53 + DN_EN_VHFUHFBAR , // 54 + DN_GAIN_ADJUST , // 55 + DN_IQTNBUF_AMP , // 56 + DN_IQTNGNBFBIAS_BST , // 57 + RFSYN_EN_OUTMUX , // 58 + RFSYN_SEL_VCO_OUT , // 59 + RFSYN_SEL_VCO_HI , // 60 + RFSYN_SEL_DIVM , // 61 + RFSYN_RF_DIV_BIAS , // 62 + DN_SEL_FREQ , // 63 + RFSYN_VCO_BIAS , // 64 + CHCAL_INT_MOD_RF , // 65 + CHCAL_FRAC_MOD_RF , // 66 + RFSYN_LPF_R , // 67 + CHCAL_EN_INT_RF , // 68 + TG_LO_DIVVAL , // 69 + TG_LO_SELVAL , // 70 + TG_DIV_VAL , // 71 + TG_VCO_BIAS , // 72 + SEQ_EXTPOWERUP , // 73 + OVERRIDE_2 , // 74 + OVERRIDE_3 , // 75 + OVERRIDE_4 , // 76 + SEQ_FSM_PULSE , // 77 + GPIO_4B, // 78 + GPIO_3B, // 79 + GPIO_4, // 80 + GPIO_3, // 81 + GPIO_1B, // 82 + DAC_A_ENABLE , // 83 + DAC_B_ENABLE , // 84 + DAC_DIN_A , // 85 + DAC_DIN_B , // 86 +#ifdef _MXL_PRODUCTION + RFSYN_EN_DIV, // 87 + RFSYN_DIVM, // 88 + DN_BYPASS_AGC_I2C // 89 +#endif + +} MXL5005_ControlName ; + + + + + + + + + + + + + + + +// MaxLinear source code - MXL5005_c.h + + + +// MXL5005.h : main header file for the MXL5005 DLL +// +//#pragma once + +//#include "Common.h" +#ifdef _MXL_INTERNAL +#include "Common_MXL.h" +#endif + +void InitTunerControls( Tuner_struct *Tuner) ; + +_u16 MXL_BlockInit( Tuner_struct *Tuner ) ; + +_u16 MXL5005_RegisterInit (Tuner_struct * Tuner) ; +_u16 MXL5005_ControlInit (Tuner_struct *Tuner) ; + +#ifdef _MXL_INTERNAL + _u16 MXL5005_MXLControlInit(Tuner_struct *Tuner) ; +#endif + +_u16 MXL5005_TunerConfig(Tuner_struct *Tuner, + _u8 Mode, // 0: Analog Mode ; 1: Digital Mode + _u8 IF_mode, // for Analog Mode, 0: zero IF; 1: low IF + _u32 Bandwidth, // filter channel bandwidth (6, 7, 8) + _u32 IF_out, // Desired IF Out Frequency + _u32 Fxtal, // XTAL Frequency + _u8 AGC_Mode, // AGC Mode - Dual AGC: 0, Single AGC: 1 + _u16 TOP, // 0: Dual AGC; Value: take over point + _u16 IF_OUT_LOAD,// IF Out Load Resistor (200 / 300 Ohms) + _u8 CLOCK_OUT, // 0: turn off clock out; 1: turn on clock out + _u8 DIV_OUT, // 4MHz or 16MHz + _u8 CAPSELECT, // 0: disable On-Chip pulling cap; 1: enable + _u8 EN_RSSI, // 0: disable RSSI; 1: enable RSSI + _u8 Mod_Type, // Modulation Type; + // 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable + _u8 TF_Type // Tracking Filter Type + // 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H + ) ; + +void MXL_SynthIFLO_Calc(Tuner_struct *Tuner) ; +void MXL_SynthRFTGLO_Calc(Tuner_struct *Tuner) ; +_u16 MXL_RegWrite(Tuner_struct *Tuner, _u8 RegNum, _u8 RegVal) ; +_u16 MXL_RegRead(Tuner_struct *Tuner, _u8 RegNum, _u8 *RegVal) ; +_u16 MXL_ControlWrite(Tuner_struct *Tuner, _u16 ControlNum, _u32 value) ; +_u16 MXL_ControlWrite_Group(Tuner_struct *Tuner, _u16 ControlNum, _u32 value, _u16 controlGroup) ; +_u16 MXL_ControlRead(Tuner_struct *Tuner, _u16 ControlNum, _u32 * value) ; +_u16 MXL_ControlRegRead(Tuner_struct *Tuner, _u16 ControlNum, _u8 *RegNum, int * count) ; +void MXL_RegWriteBit(Tuner_struct *Tuner, _u8 address, _u8 bit, _u8 bitVal); +_u16 MXL_IFSynthInit( Tuner_struct * Tuner ) ; +_u16 MXL_TuneRF(Tuner_struct *Tuner, _u32 RF_Freq) ; +_u16 MXL_OverwriteICDefault( Tuner_struct *Tuner) ; +_u16 MXL_SetGPIO(Tuner_struct *Tuner, _u8 GPIO_Num, _u8 GPIO_Val) ; +_u32 MXL_Ceiling( _u32 value, _u32 resolution ) ; +_u32 MXL_GetXtalInt(_u32 Xtal_Freq) ; + +_u16 MXL_GetInitRegister(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) ; +_u16 MXL_GetCHRegister(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) ; +_u16 MXL_GetCHRegister_ZeroIF(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) ; +_u16 MXL_GetCHRegister_LowIF(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) ; +_u16 MXL_GetMasterControl(_u8 *MasterReg, int state) ; + +#ifdef _MXL_PRODUCTION +_u16 MXL_VCORange_Test(Tuner_struct *Tuner, int VCO_Range) ; +_u16 MXL_Hystersis_Test(Tuner_struct *Tuner, int Hystersis) ; +#endif + + + + + + + + + + + + + + + + + + + + + + + +// The following context is MxL5005S tuner API source code + + + + + +/** + +@file + +@brief MxL5005S tuner module declaration + +One can manipulate MxL5005S tuner through MxL5005S module. +MxL5005S module is derived from tuner module. + +*/ + + + +#include "tuner_base.h" + + + + + +// Definitions + +// Constants +#define MXL5005S_REG_WRITING_TABLE_LEN_MAX 104 +#define MXL5005S_LATCH_BYTE 0xfe + +// Register address, MSB, and LSB +#define MXL5005S_BB_IQSWAP_ADDR 59 +#define MXL5005S_BB_IQSWAP_MSB 0 +#define MXL5005S_BB_IQSWAP_LSB 0 + +#define MXL5005S_BB_DLPF_BANDSEL_ADDR 53 +#define MXL5005S_BB_DLPF_BANDSEL_MSB 4 +#define MXL5005S_BB_DLPF_BANDSEL_LSB 3 + + + +// Standard modes +enum +{ + MXL5005S_STANDARD_DVBT, + MXL5005S_STANDARD_ATSC, +}; +#define MXL5005S_STANDARD_MODE_NUM 2 + + +// Bandwidth modes +enum +{ + MXL5005S_BANDWIDTH_6MHZ = 6000000, + MXL5005S_BANDWIDTH_7MHZ = 7000000, + MXL5005S_BANDWIDTH_8MHZ = 8000000, +}; +#define MXL5005S_BANDWIDTH_MODE_NUM 3 + + +// Top modes +enum +{ + MXL5005S_TOP_5P5 = 55, + MXL5005S_TOP_7P2 = 72, + MXL5005S_TOP_9P2 = 92, + MXL5005S_TOP_11P0 = 110, + MXL5005S_TOP_12P9 = 129, + MXL5005S_TOP_14P7 = 147, + MXL5005S_TOP_16P8 = 168, + MXL5005S_TOP_19P4 = 194, + MXL5005S_TOP_21P2 = 212, + MXL5005S_TOP_23P2 = 232, + MXL5005S_TOP_25P2 = 252, + MXL5005S_TOP_27P1 = 271, + MXL5005S_TOP_29P2 = 292, + MXL5005S_TOP_31P7 = 317, + MXL5005S_TOP_34P9 = 349, +}; + + +// IF output load +enum +{ + MXL5005S_IF_OUTPUT_LOAD_200_OHM = 200, + MXL5005S_IF_OUTPUT_LOAD_300_OHM = 300, +}; + + + + + +/// MxL5005S extra module alias +typedef struct MXL5005S_EXTRA_MODULE_TAG MXL5005S_EXTRA_MODULE; + + + + + +// MxL5005S register setting function pointer +typedef int +(*MXL5005S_FP_SET_REGS_WITH_TABLE)( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + unsigned char *pAddrTable, + unsigned char *pByteTable, + int TableLen + ); + + +// MxL5005S register mask bits setting function pointer +typedef int +(*MXL5005S_FP_SET_REG_MASK_BITS)( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + unsigned char RegAddr, + unsigned char Msb, + unsigned char Lsb, + const unsigned char WritingValue + ); + + +// MxL5005S spectrum mode setting function pointer +typedef int +(*MXL5005S_FP_SET_SPECTRUM_MODE)( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + int SpectrumMode + ); + + +// MxL5005S bandwidth setting function pointer +typedef int +(*MXL5005S_FP_SET_BANDWIDTH_HZ)( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + unsigned long BandwidthHz + ); + + + + + +// MxL5005S extra module +struct MXL5005S_EXTRA_MODULE_TAG +{ + // MxL5005S function pointers + MXL5005S_FP_SET_REGS_WITH_TABLE SetRegsWithTable; + MXL5005S_FP_SET_REG_MASK_BITS SetRegMaskBits; + MXL5005S_FP_SET_SPECTRUM_MODE SetSpectrumMode; + MXL5005S_FP_SET_BANDWIDTH_HZ SetBandwidthHz; + + + // MxL5005S extra data + unsigned char AgcMasterByte; // Variable name in MaxLinear source code: AGC_MASTER_BYTE + + // MaxLinear defined struct + Tuner_struct MxlDefinedTunerStructure; +}; + + + + + +// Builder +void +BuildMxl5005sModule( + TUNER_MODULE **ppTuner, + TUNER_MODULE *pTunerModuleMemory, + MXL5005S_EXTRA_MODULE *pMxl5005sExtraModuleMemory, + BASE_INTERFACE_MODULE *pBaseInterfaceModuleMemory, + I2C_BRIDGE_MODULE *pI2cBridgeModuleMemory, + unsigned char DeviceAddr, + int StandardMode + ); + + + + + +// Manipulaing functions +void +mxl5005s_SetDeviceAddr( + TUNER_MODULE *pTuner, + unsigned char DeviceAddr + ); + +void +mxl5005s_GetTunerType( + TUNER_MODULE *pTuner, + int *pTunerType + ); + +int +mxl5005s_GetDeviceAddr( + TUNER_MODULE *pTuner, + unsigned char *pDeviceAddr + ); + +int +mxl5005s_Initialize( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner + ); + +int +mxl5005s_SetRfFreqHz( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + unsigned long RfFreqHz + ); + +int +mxl5005s_GetRfFreqHz( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + unsigned long *pRfFreqHz + ); + + + + + +// Extra manipulaing functions +int +mxl5005s_SetRegsWithTable( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + unsigned char *pAddrTable, + unsigned char *pByteTable, + int TableLen + ); + +int +mxl5005s_SetRegMaskBits( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + unsigned char RegAddr, + unsigned char Msb, + unsigned char Lsb, + const unsigned char WritingValue + ); + +int +mxl5005s_SetSpectrumMode( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + int SpectrumMode + ); + +int +mxl5005s_SetBandwidthHz( + struct dvb_usb_device* dib, + TUNER_MODULE *pTuner, + unsigned long BandwidthHz + ); + + + + + +// I2C birdge module demod argument setting +void +mxl5005s_SetI2cBridgeModuleTunerArg( + TUNER_MODULE *pTuner + ); + + + + + + + + + + + + + + + +#endif + -- cgit v1.1 From 2637d5b498b979b46a01690d22ecca1e5b79b903 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 1 May 2008 05:01:31 -0300 Subject: V4L/DVB (7864): mxl5005s: Cleanup #1 Cleanup #1 Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 8 +- drivers/media/common/tuners/mxl5005s.h | 773 +++++++++++---------------------- 2 files changed, 260 insertions(+), 521 deletions(-) diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index a32475f..3c43306 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -35,13 +35,7 @@ MxL5005S module is derived from tuner module. */ -#include "tuner_mxl5005s.h" -#include "tuner_demod_io.h" - - - - - +#include "mxl5005s.h" /** diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h index 8542fc1..1944d9e 100644 --- a/drivers/media/common/tuners/mxl5005s.h +++ b/drivers/media/common/tuners/mxl5005s.h @@ -23,138 +23,104 @@ */ -#ifndef __TUNER_MXL5005S_H -#define __TUNER_MXL5005S_H +#ifndef __MXL5005S_H +#define __MXL5005S_H +/* + * The following context is source code provided by MaxLinear. + * MaxLinear source code - Common.h + */ - -// The following context is source code provided by MaxLinear. - - -// MaxLinear source code - Common.h - - - -//#pragma once - -typedef unsigned char _u8; // At least 1 Byte -typedef unsigned short _u16; // At least 2 Bytes -typedef signed short _s16; -typedef unsigned long _u32; // At least 4 Bytes -typedef void * HANDLE; // Pointer to memory location +typedef void *HANDLE; /* Pointer to memory location */ #define TUNER_REGS_NUM 104 #define INITCTRL_NUM 40 + #ifdef _MXL_PRODUCTION -#define CHCTRL_NUM 39 +#define CHCTRL_NUM 39 #else -#define CHCTRL_NUM 36 +#define CHCTRL_NUM 36 #endif -#define MXLCTRL_NUM 189 - -#define MASTER_CONTROL_ADDR 9 - +#define MXLCTRL_NUM 189 +#define MASTER_CONTROL_ADDR 9 - - -// Enumeration of AGC Mode +/* Enumeration of AGC Mode */ typedef enum { - MXL_DUAL_AGC = 0 , + MXL_DUAL_AGC = 0, MXL_SINGLE_AGC -} AGC_Mode ; +} AGC_Mode; -// -// Enumeration of Master Control Register State -// +/* Enumeration of Master Control Register State */ typedef enum { - MC_LOAD_START = 1 , - MC_POWER_DOWN , - MC_SYNTH_RESET , + MC_LOAD_START = 1, + MC_POWER_DOWN, + MC_SYNTH_RESET, MC_SEQ_OFF -} Master_Control_State ; +} Master_Control_State; -// -// Enumeration of MXL5005 Tuner Mode -// +/* Enumeration of MXL5005 Tuner Mode */ typedef enum { - MXL_ANALOG_MODE = 0 , + MXL_ANALOG_MODE = 0, MXL_DIGITAL_MODE +} Tuner_Mode; -} Tuner_Mode ; - -// -// Enumeration of MXL5005 Tuner IF Mode -// +/* Enumeration of MXL5005 Tuner IF Mode */ typedef enum { - MXL_ZERO_IF = 0 , + MXL_ZERO_IF = 0, MXL_LOW_IF +} Tuner_IF_Mode; -} Tuner_IF_Mode ; - -// -// Enumeration of MXL5005 Tuner Clock Out Mode -// +/* Enumeration of MXL5005 Tuner Clock Out Mode */ typedef enum { - MXL_CLOCK_OUT_DISABLE = 0 , + MXL_CLOCK_OUT_DISABLE = 0, MXL_CLOCK_OUT_ENABLE -} Tuner_Clock_Out ; +} Tuner_Clock_Out; -// -// Enumeration of MXL5005 Tuner Div Out Mode -// +/* Enumeration of MXL5005 Tuner Div Out Mode */ typedef enum { - MXL_DIV_OUT_1 = 0 , + MXL_DIV_OUT_1 = 0, MXL_DIV_OUT_4 -} Tuner_Div_Out ; +} Tuner_Div_Out; -// -// Enumeration of MXL5005 Tuner Pull-up Cap Select Mode -// +/* Enumeration of MXL5005 Tuner Pull-up Cap Select Mode */ typedef enum { - MXL_CAP_SEL_DISABLE = 0 , + MXL_CAP_SEL_DISABLE = 0, MXL_CAP_SEL_ENABLE -} Tuner_Cap_Select ; +} Tuner_Cap_Select; -// -// Enumeration of MXL5005 Tuner RSSI Mode -// +/* Enumeration of MXL5005 Tuner RSSI Mode */ typedef enum { - MXL_RSSI_DISABLE = 0 , + MXL_RSSI_DISABLE = 0, MXL_RSSI_ENABLE -} Tuner_RSSI ; +} Tuner_RSSI; -// -// Enumeration of MXL5005 Tuner Modulation Type -// +/* Enumeration of MXL5005 Tuner Modulation Type */ typedef enum { - MXL_DEFAULT_MODULATION = 0 , + MXL_DEFAULT_MODULATION = 0, MXL_DVBT, MXL_ATSC, MXL_QAM, MXL_ANALOG_CABLE, MXL_ANALOG_OTA +} Tuner_Modu_Type; -} Tuner_Modu_Type ; - -// -// Enumeration of MXL5005 Tuner Tracking Filter Type -// +/* Enumeration of MXL5005 Tuner Tracking Filter Type */ typedef enum { - MXL_TF_DEFAULT = 0 , + MXL_TF_DEFAULT = 0, MXL_TF_OFF, MXL_TF_C, MXL_TF_C_H, @@ -165,316 +131,233 @@ typedef enum MXL_TF_E_2, MXL_TF_E_NA, MXL_TF_G +} Tuner_TF_Type; - -} Tuner_TF_Type ; - - -// -// MXL5005 Tuner Register Struct -// +/* MXL5005 Tuner Register Struct */ typedef struct _TunerReg_struct { - _u16 Reg_Num ; // Tuner Register Address - _u16 Reg_Val ; // Current sofware programmed value waiting to be writen -} TunerReg_struct ; + u16 Reg_Num; /* Tuner Register Address */ + u16 Reg_Val; /* Current sofware programmed value waiting to be writen */ +} TunerReg_struct; -// -// MXL5005 Tuner Control Struct -// +/* MXL5005 Tuner Control Struct */ typedef struct _TunerControl_struct { - _u16 Ctrl_Num ; // Control Number - _u16 size ; // Number of bits to represent Value - _u16 addr[25] ; // Array of Tuner Register Address for each bit position - _u16 bit[25] ; // Array of bit position in Register Address for each bit position - _u16 val[25] ; // Binary representation of Value -} TunerControl_struct ; - -// -// MXL5005 Tuner Struct -// + u16 Ctrl_Num; /* Control Number */ + u16 size; /* Number of bits to represent Value */ + u16 addr[25]; /* Array of Tuner Register Address for each bit position */ + u16 bit[25]; /* Array of bit position in Register Address for each bit position */ + u16 val[25]; /* Binary representation of Value */ +} TunerControl_struct; + +/* MXL5005 Tuner Struct */ typedef struct _Tuner_struct { - _u8 Mode ; // 0: Analog Mode ; 1: Digital Mode - _u8 IF_Mode ; // for Analog Mode, 0: zero IF; 1: low IF - _u32 Chan_Bandwidth ; // filter channel bandwidth (6, 7, 8) - _u32 IF_OUT ; // Desired IF Out Frequency - _u16 IF_OUT_LOAD ; // IF Out Load Resistor (200/300 Ohms) - _u32 RF_IN ; // RF Input Frequency - _u32 Fxtal ; // XTAL Frequency - _u8 AGC_Mode ; // AGC Mode 0: Dual AGC; 1: Single AGC - _u16 TOP ; // Value: take over point - _u8 CLOCK_OUT ; // 0: turn off clock out; 1: turn on clock out - _u8 DIV_OUT ; // 4MHz or 16MHz - _u8 CAPSELECT ; // 0: disable On-Chip pulling cap; 1: enable - _u8 EN_RSSI ; // 0: disable RSSI; 1: enable RSSI - _u8 Mod_Type ; // Modulation Type; - // 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable - _u8 TF_Type ; // Tracking Filter Type - // 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H - - // Calculated Settings - _u32 RF_LO ; // Synth RF LO Frequency - _u32 IF_LO ; // Synth IF LO Frequency - _u32 TG_LO ; // Synth TG_LO Frequency - - // Pointers to ControlName Arrays - _u16 Init_Ctrl_Num ; // Number of INIT Control Names - TunerControl_struct Init_Ctrl[INITCTRL_NUM] ; // INIT Control Names Array Pointer - _u16 CH_Ctrl_Num ; // Number of CH Control Names - TunerControl_struct CH_Ctrl[CHCTRL_NUM] ; // CH Control Name Array Pointer - _u16 MXL_Ctrl_Num ; // Number of MXL Control Names - TunerControl_struct MXL_Ctrl[MXLCTRL_NUM] ; // MXL Control Name Array Pointer - - // Pointer to Tuner Register Array - _u16 TunerRegs_Num ; // Number of Tuner Registers - TunerReg_struct TunerRegs[TUNER_REGS_NUM] ; // Tuner Register Array Pointer -} Tuner_struct ; - - + u8 Mode; /* 0: Analog Mode ; 1: Digital Mode */ + u8 IF_Mode; /* for Analog Mode, 0: zero IF; 1: low IF */ + u32 Chan_Bandwidth; /* filter channel bandwidth (6, 7, 8) */ + u32 IF_OUT; /* Desired IF Out Frequency */ + u16 IF_OUT_LOAD; /* IF Out Load Resistor (200/300 Ohms) */ + u32 RF_IN; /* RF Input Frequency */ + u32 Fxtal; /* XTAL Frequency */ + u8 AGC_Mode; /* AGC Mode 0: Dual AGC; 1: Single AGC */ + u16 TOP; /* Value: take over point */ + u8 CLOCK_OUT; /* 0: turn off clock out; 1: turn on clock out */ + u8 DIV_OUT; /* 4MHz or 16MHz */ + u8 CAPSELECT; /* 0: disable On-Chip pulling cap; 1: enable */ + u8 EN_RSSI; /* 0: disable RSSI; 1: enable RSSI */ + u8 Mod_Type; /* Modulation Type; */ + /* 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable */ + u8 TF_Type; /* Tracking Filter Type */ + /* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */ + + /* Calculated Settings */ + u32 RF_LO; /* Synth RF LO Frequency */ + u32 IF_LO; /* Synth IF LO Frequency */ + u32 TG_LO; /* Synth TG_LO Frequency */ + + /* Pointers to ControlName Arrays */ + u16 Init_Ctrl_Num; /* Number of INIT Control Names */ + TunerControl_struct + Init_Ctrl[INITCTRL_NUM]; /* INIT Control Names Array Pointer */ + + u16 CH_Ctrl_Num; /* Number of CH Control Names */ + TunerControl_struct + CH_Ctrl[CHCTRL_NUM]; /* CH Control Name Array Pointer */ + + u16 MXL_Ctrl_Num; /* Number of MXL Control Names */ + TunerControl_struct + MXL_Ctrl[MXLCTRL_NUM]; /* MXL Control Name Array Pointer */ + + /* Pointer to Tuner Register Array */ + u16 TunerRegs_Num; /* Number of Tuner Registers */ + TunerReg_struct + TunerRegs[TUNER_REGS_NUM]; /* Tuner Register Array Pointer */ + +} Tuner_struct; typedef enum { - // - // Initialization Control Names - // - DN_IQTN_AMP_CUT = 1 , // 1 - BB_MODE , // 2 - BB_BUF , // 3 - BB_BUF_OA , // 4 - BB_ALPF_BANDSELECT , // 5 - BB_IQSWAP , // 6 - BB_DLPF_BANDSEL , // 7 - RFSYN_CHP_GAIN , // 8 - RFSYN_EN_CHP_HIGAIN , // 9 - AGC_IF , // 10 - AGC_RF , // 11 - IF_DIVVAL , // 12 - IF_VCO_BIAS , // 13 - CHCAL_INT_MOD_IF , // 14 - CHCAL_FRAC_MOD_IF , // 15 - DRV_RES_SEL , // 16 - I_DRIVER , // 17 - EN_AAF , // 18 - EN_3P , // 19 - EN_AUX_3P , // 20 - SEL_AAF_BAND , // 21 - SEQ_ENCLK16_CLK_OUT , // 22 - SEQ_SEL4_16B , // 23 - XTAL_CAPSELECT , // 24 - IF_SEL_DBL , // 25 - RFSYN_R_DIV , // 26 - SEQ_EXTSYNTHCALIF , // 27 - SEQ_EXTDCCAL , // 28 - AGC_EN_RSSI , // 29 - RFA_ENCLKRFAGC , // 30 - RFA_RSSI_REFH , // 31 - RFA_RSSI_REF , // 32 - RFA_RSSI_REFL , // 33 - RFA_FLR , // 34 - RFA_CEIL , // 35 - SEQ_EXTIQFSMPULSE , // 36 - OVERRIDE_1 , // 37 - BB_INITSTATE_DLPF_TUNE, // 38 - TG_R_DIV, // 39 - EN_CHP_LIN_B , // 40 - - // - // Channel Change Control Names - // - DN_POLY = 51 , // 51 - DN_RFGAIN , // 52 - DN_CAP_RFLPF , // 53 - DN_EN_VHFUHFBAR , // 54 - DN_GAIN_ADJUST , // 55 - DN_IQTNBUF_AMP , // 56 - DN_IQTNGNBFBIAS_BST , // 57 - RFSYN_EN_OUTMUX , // 58 - RFSYN_SEL_VCO_OUT , // 59 - RFSYN_SEL_VCO_HI , // 60 - RFSYN_SEL_DIVM , // 61 - RFSYN_RF_DIV_BIAS , // 62 - DN_SEL_FREQ , // 63 - RFSYN_VCO_BIAS , // 64 - CHCAL_INT_MOD_RF , // 65 - CHCAL_FRAC_MOD_RF , // 66 - RFSYN_LPF_R , // 67 - CHCAL_EN_INT_RF , // 68 - TG_LO_DIVVAL , // 69 - TG_LO_SELVAL , // 70 - TG_DIV_VAL , // 71 - TG_VCO_BIAS , // 72 - SEQ_EXTPOWERUP , // 73 - OVERRIDE_2 , // 74 - OVERRIDE_3 , // 75 - OVERRIDE_4 , // 76 - SEQ_FSM_PULSE , // 77 - GPIO_4B, // 78 - GPIO_3B, // 79 - GPIO_4, // 80 - GPIO_3, // 81 - GPIO_1B, // 82 - DAC_A_ENABLE , // 83 - DAC_B_ENABLE , // 84 - DAC_DIN_A , // 85 - DAC_DIN_B , // 86 + /* Initialization Control Names */ + DN_IQTN_AMP_CUT = 1, /* 1 */ + BB_MODE, /* 2 */ + BB_BUF, /* 3 */ + BB_BUF_OA, /* 4 */ + BB_ALPF_BANDSELECT, /* 5 */ + BB_IQSWAP, /* 6 */ + BB_DLPF_BANDSEL, /* 7 */ + RFSYN_CHP_GAIN, /* 8 */ + RFSYN_EN_CHP_HIGAIN, /* 9 */ + AGC_IF, /* 10 */ + AGC_RF, /* 11 */ + IF_DIVVAL, /* 12 */ + IF_VCO_BIAS, /* 13 */ + CHCAL_INT_MOD_IF, /* 14 */ + CHCAL_FRAC_MOD_IF, /* 15 */ + DRV_RES_SEL, /* 16 */ + I_DRIVER, /* 17 */ + EN_AAF, /* 18 */ + EN_3P, /* 19 */ + EN_AUX_3P, /* 20 */ + SEL_AAF_BAND, /* 21 */ + SEQ_ENCLK16_CLK_OUT, /* 22 */ + SEQ_SEL4_16B, /* 23 */ + XTAL_CAPSELECT, /* 24 */ + IF_SEL_DBL, /* 25 */ + RFSYN_R_DIV, /* 26 */ + SEQ_EXTSYNTHCALIF, /* 27 */ + SEQ_EXTDCCAL, /* 28 */ + AGC_EN_RSSI, /* 29 */ + RFA_ENCLKRFAGC, /* 30 */ + RFA_RSSI_REFH, /* 31 */ + RFA_RSSI_REF, /* 32 */ + RFA_RSSI_REFL, /* 33 */ + RFA_FLR, /* 34 */ + RFA_CEIL, /* 35 */ + SEQ_EXTIQFSMPULSE, /* 36 */ + OVERRIDE_1, /* 37 */ + BB_INITSTATE_DLPF_TUNE, /* 38 */ + TG_R_DIV, /* 39 */ + EN_CHP_LIN_B, /* 40 */ + + /* Channel Change Control Names */ + DN_POLY = 51, /* 51 */ + DN_RFGAIN, /* 52 */ + DN_CAP_RFLPF, /* 53 */ + DN_EN_VHFUHFBAR, /* 54 */ + DN_GAIN_ADJUST, /* 55 */ + DN_IQTNBUF_AMP, /* 56 */ + DN_IQTNGNBFBIAS_BST, /* 57 */ + RFSYN_EN_OUTMUX, /* 58 */ + RFSYN_SEL_VCO_OUT, /* 59 */ + RFSYN_SEL_VCO_HI, /* 60 */ + RFSYN_SEL_DIVM, /* 61 */ + RFSYN_RF_DIV_BIAS, /* 62 */ + DN_SEL_FREQ, /* 63 */ + RFSYN_VCO_BIAS, /* 64 */ + CHCAL_INT_MOD_RF, /* 65 */ + CHCAL_FRAC_MOD_RF, /* 66 */ + RFSYN_LPF_R, /* 67 */ + CHCAL_EN_INT_RF, /* 68 */ + TG_LO_DIVVAL, /* 69 */ + TG_LO_SELVAL, /* 70 */ + TG_DIV_VAL, /* 71 */ + TG_VCO_BIAS, /* 72 */ + SEQ_EXTPOWERUP, /* 73 */ + OVERRIDE_2, /* 74 */ + OVERRIDE_3, /* 75 */ + OVERRIDE_4, /* 76 */ + SEQ_FSM_PULSE, /* 77 */ + GPIO_4B, /* 78 */ + GPIO_3B, /* 79 */ + GPIO_4, /* 80 */ + GPIO_3, /* 81 */ + GPIO_1B, /* 82 */ + DAC_A_ENABLE, /* 83 */ + DAC_B_ENABLE, /* 84 */ + DAC_DIN_A, /* 85 */ + DAC_DIN_B, /* 86 */ #ifdef _MXL_PRODUCTION - RFSYN_EN_DIV, // 87 - RFSYN_DIVM, // 88 - DN_BYPASS_AGC_I2C // 89 + RFSYN_EN_DIV, /* 87 */ + RFSYN_DIVM, /* 88 */ + DN_BYPASS_AGC_I2C /* 89 */ #endif +} MXL5005_ControlName; -} MXL5005_ControlName ; - - +/* End of common.h */ +/* + * The following context is source code provided by MaxLinear. + * MaxLinear source code - Common_MXL.h (?) + */ - - - - - - - - - - - -// MaxLinear source code - MXL5005_c.h - - - -// MXL5005.h : main header file for the MXL5005 DLL -// -//#pragma once - -//#include "Common.h" +void InitTunerControls(Tuner_struct *Tuner); +u16 MXL_BlockInit(Tuner_struct *Tuner); +u16 MXL5005_RegisterInit(Tuner_struct *Tuner); +u16 MXL5005_ControlInit(Tuner_struct *Tuner); #ifdef _MXL_INTERNAL -#include "Common_MXL.h" +u16 MXL5005_MXLControlInit(Tuner_struct *Tuner); #endif -void InitTunerControls( Tuner_struct *Tuner) ; - -_u16 MXL_BlockInit( Tuner_struct *Tuner ) ; - -_u16 MXL5005_RegisterInit (Tuner_struct * Tuner) ; -_u16 MXL5005_ControlInit (Tuner_struct *Tuner) ; - -#ifdef _MXL_INTERNAL - _u16 MXL5005_MXLControlInit(Tuner_struct *Tuner) ; -#endif +u16 MXL5005_TunerConfig(Tuner_struct *Tuner, + u8 Mode, /* 0: Analog Mode ; 1: Digital Mode */ + u8 IF_mode, /* for Analog Mode, 0: zero IF; 1: low IF */ + u32 Bandwidth, /* filter channel bandwidth (6, 7, 8) */ + u32 IF_out, /* Desired IF Out Frequency */ + u32 Fxtal, /* XTAL Frequency */ + u8 AGC_Mode, /* AGC Mode - Dual AGC: 0, Single AGC: 1 */ + u16 TOP, /* 0: Dual AGC; Value: take over point */ + u16 IF_OUT_LOAD, /* IF Out Load Resistor (200 / 300 Ohms) */ + u8 CLOCK_OUT, /* 0: turn off clock out; 1: turn on clock out */ + u8 DIV_OUT, /* 4MHz or 16MHz */ + u8 CAPSELECT, /* 0: disable On-Chip pulling cap; 1: enable */ + u8 EN_RSSI, /* 0: disable RSSI; 1: enable RSSI */ + u8 Mod_Type, /* Modulation Type; */ + /* 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable */ + u8 TF_Type /* Tracking Filter Type */ + /* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */ + ); -_u16 MXL5005_TunerConfig(Tuner_struct *Tuner, - _u8 Mode, // 0: Analog Mode ; 1: Digital Mode - _u8 IF_mode, // for Analog Mode, 0: zero IF; 1: low IF - _u32 Bandwidth, // filter channel bandwidth (6, 7, 8) - _u32 IF_out, // Desired IF Out Frequency - _u32 Fxtal, // XTAL Frequency - _u8 AGC_Mode, // AGC Mode - Dual AGC: 0, Single AGC: 1 - _u16 TOP, // 0: Dual AGC; Value: take over point - _u16 IF_OUT_LOAD,// IF Out Load Resistor (200 / 300 Ohms) - _u8 CLOCK_OUT, // 0: turn off clock out; 1: turn on clock out - _u8 DIV_OUT, // 4MHz or 16MHz - _u8 CAPSELECT, // 0: disable On-Chip pulling cap; 1: enable - _u8 EN_RSSI, // 0: disable RSSI; 1: enable RSSI - _u8 Mod_Type, // Modulation Type; - // 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable - _u8 TF_Type // Tracking Filter Type - // 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H - ) ; - -void MXL_SynthIFLO_Calc(Tuner_struct *Tuner) ; -void MXL_SynthRFTGLO_Calc(Tuner_struct *Tuner) ; -_u16 MXL_RegWrite(Tuner_struct *Tuner, _u8 RegNum, _u8 RegVal) ; -_u16 MXL_RegRead(Tuner_struct *Tuner, _u8 RegNum, _u8 *RegVal) ; -_u16 MXL_ControlWrite(Tuner_struct *Tuner, _u16 ControlNum, _u32 value) ; -_u16 MXL_ControlWrite_Group(Tuner_struct *Tuner, _u16 ControlNum, _u32 value, _u16 controlGroup) ; -_u16 MXL_ControlRead(Tuner_struct *Tuner, _u16 ControlNum, _u32 * value) ; -_u16 MXL_ControlRegRead(Tuner_struct *Tuner, _u16 ControlNum, _u8 *RegNum, int * count) ; -void MXL_RegWriteBit(Tuner_struct *Tuner, _u8 address, _u8 bit, _u8 bitVal); -_u16 MXL_IFSynthInit( Tuner_struct * Tuner ) ; -_u16 MXL_TuneRF(Tuner_struct *Tuner, _u32 RF_Freq) ; -_u16 MXL_OverwriteICDefault( Tuner_struct *Tuner) ; -_u16 MXL_SetGPIO(Tuner_struct *Tuner, _u8 GPIO_Num, _u8 GPIO_Val) ; -_u32 MXL_Ceiling( _u32 value, _u32 resolution ) ; -_u32 MXL_GetXtalInt(_u32 Xtal_Freq) ; - -_u16 MXL_GetInitRegister(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) ; -_u16 MXL_GetCHRegister(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) ; -_u16 MXL_GetCHRegister_ZeroIF(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) ; -_u16 MXL_GetCHRegister_LowIF(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) ; -_u16 MXL_GetMasterControl(_u8 *MasterReg, int state) ; +void MXL_SynthIFLO_Calc(Tuner_struct *Tuner); +void MXL_SynthRFTGLO_Calc(Tuner_struct *Tuner); +u16 MXL_RegWrite(Tuner_struct *Tuner, u8 RegNum, u8 RegVal); +u16 MXL_RegRead(Tuner_struct *Tuner, u8 RegNum, u8 *RegVal); +u16 MXL_ControlWrite(Tuner_struct *Tuner, u16 ControlNum, u32 value); +u16 MXL_ControlWrite_Group(Tuner_struct *Tuner, u16 ControlNum, u32 value, u16 controlGroup); +u16 MXL_ControlRead(Tuner_struct *Tuner, u16 ControlNum, u32 * value); +u16 MXL_ControlRegRead(Tuner_struct *Tuner, u16 ControlNum, u8 *RegNum, int *count); +void MXL_RegWriteBit(Tuner_struct *Tuner, u8 address, u8 bit, u8 bitVal); +u16 MXL_IFSynthInit(Tuner_struct * Tuner ); +u16 MXL_TuneRF(Tuner_struct *Tuner, u32 RF_Freq); +u16 MXL_OverwriteICDefault(Tuner_struct *Tuner); +u16 MXL_SetGPIO(Tuner_struct *Tuner, u8 GPIO_Num, u8 GPIO_Val); +u32 MXL_Ceiling(u32 value, u32 resolution); +u32 MXL_GetXtalInt(u32 Xtal_Freq); + +u16 MXL_GetInitRegister(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count); +u16 MXL_GetCHRegister(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count); +u16 MXL_GetCHRegister_ZeroIF(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count); +u16 MXL_GetCHRegister_LowIF(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count); +u16 MXL_GetMasterControl(u8 *MasterReg, int state); #ifdef _MXL_PRODUCTION -_u16 MXL_VCORange_Test(Tuner_struct *Tuner, int VCO_Range) ; -_u16 MXL_Hystersis_Test(Tuner_struct *Tuner, int Hystersis) ; +u16 MXL_VCORange_Test(Tuner_struct *Tuner, int VCO_Range); +u16 MXL_Hystersis_Test(Tuner_struct *Tuner, int Hystersis); #endif +/* Constants */ +#define MXL5005S_REG_WRITING_TABLE_LEN_MAX 104 +#define MXL5005S_LATCH_BYTE 0xfe - - - - - - - - - - - - - - - - - - - - - -// The following context is MxL5005S tuner API source code - - - - - -/** - -@file - -@brief MxL5005S tuner module declaration - -One can manipulate MxL5005S tuner through MxL5005S module. -MxL5005S module is derived from tuner module. - -*/ - - - -#include "tuner_base.h" - - - - - -// Definitions - -// Constants -#define MXL5005S_REG_WRITING_TABLE_LEN_MAX 104 -#define MXL5005S_LATCH_BYTE 0xfe - -// Register address, MSB, and LSB -#define MXL5005S_BB_IQSWAP_ADDR 59 -#define MXL5005S_BB_IQSWAP_MSB 0 -#define MXL5005S_BB_IQSWAP_LSB 0 +/* Register address, MSB, and LSB */ +#define MXL5005S_BB_IQSWAP_ADDR 59 +#define MXL5005S_BB_IQSWAP_MSB 0 +#define MXL5005S_BB_IQSWAP_LSB 0 #define MXL5005S_BB_DLPF_BANDSEL_ADDR 53 #define MXL5005S_BB_DLPF_BANDSEL_MSB 4 #define MXL5005S_BB_DLPF_BANDSEL_LSB 3 - - -// Standard modes +/* Standard modes */ enum { MXL5005S_STANDARD_DVBT, @@ -482,8 +365,7 @@ enum }; #define MXL5005S_STANDARD_MODE_NUM 2 - -// Bandwidth modes +/* Bandwidth modes */ enum { MXL5005S_BANDWIDTH_6MHZ = 6000000, @@ -492,8 +374,7 @@ enum }; #define MXL5005S_BANDWIDTH_MODE_NUM 3 - -// Top modes +/* Top modes */ enum { MXL5005S_TOP_5P5 = 55, @@ -513,29 +394,20 @@ enum MXL5005S_TOP_34P9 = 349, }; - -// IF output load +/* IF output load */ enum { MXL5005S_IF_OUTPUT_LOAD_200_OHM = 200, MXL5005S_IF_OUTPUT_LOAD_300_OHM = 300, }; - - - - -/// MxL5005S extra module alias +/* MxL5005S extra module alias */ typedef struct MXL5005S_EXTRA_MODULE_TAG MXL5005S_EXTRA_MODULE; - - - - -// MxL5005S register setting function pointer +/* MxL5005S register setting function pointer */ typedef int (*MXL5005S_FP_SET_REGS_WITH_TABLE)( - struct dvb_usb_device* dib, + struct dvb_usb_device* dib, TUNER_MODULE *pTuner, unsigned char *pAddrTable, unsigned char *pByteTable, @@ -543,10 +415,10 @@ typedef int ); -// MxL5005S register mask bits setting function pointer +/* MxL5005S register mask bits setting function pointer */ typedef int (*MXL5005S_FP_SET_REG_MASK_BITS)( - struct dvb_usb_device* dib, + struct dvb_usb_device* dib, TUNER_MODULE *pTuner, unsigned char RegAddr, unsigned char Msb, @@ -554,17 +426,15 @@ typedef int const unsigned char WritingValue ); - -// MxL5005S spectrum mode setting function pointer +/* MxL5005S spectrum mode setting function pointer */ typedef int (*MXL5005S_FP_SET_SPECTRUM_MODE)( - struct dvb_usb_device* dib, + struct dvb_usb_device* dib, TUNER_MODULE *pTuner, int SpectrumMode ); - -// MxL5005S bandwidth setting function pointer +/* MxL5005S bandwidth setting function pointer */ typedef int (*MXL5005S_FP_SET_BANDWIDTH_HZ)( struct dvb_usb_device* dib, @@ -572,147 +442,22 @@ typedef int unsigned long BandwidthHz ); - - - - -// MxL5005S extra module +/* MxL5005S extra module */ struct MXL5005S_EXTRA_MODULE_TAG { - // MxL5005S function pointers + /* MxL5005S function pointers */ MXL5005S_FP_SET_REGS_WITH_TABLE SetRegsWithTable; MXL5005S_FP_SET_REG_MASK_BITS SetRegMaskBits; MXL5005S_FP_SET_SPECTRUM_MODE SetSpectrumMode; MXL5005S_FP_SET_BANDWIDTH_HZ SetBandwidthHz; + /* MxL5005S extra data */ + unsigned char AgcMasterByte; /* Variable name in MaxLinear source code: AGC_MASTER_BYTE */ - // MxL5005S extra data - unsigned char AgcMasterByte; // Variable name in MaxLinear source code: AGC_MASTER_BYTE - - // MaxLinear defined struct + /* MaxLinear defined struct */ Tuner_struct MxlDefinedTunerStructure; }; +/* End of common_mxl.h (?) */ - - - - -// Builder -void -BuildMxl5005sModule( - TUNER_MODULE **ppTuner, - TUNER_MODULE *pTunerModuleMemory, - MXL5005S_EXTRA_MODULE *pMxl5005sExtraModuleMemory, - BASE_INTERFACE_MODULE *pBaseInterfaceModuleMemory, - I2C_BRIDGE_MODULE *pI2cBridgeModuleMemory, - unsigned char DeviceAddr, - int StandardMode - ); - - - - - -// Manipulaing functions -void -mxl5005s_SetDeviceAddr( - TUNER_MODULE *pTuner, - unsigned char DeviceAddr - ); - -void -mxl5005s_GetTunerType( - TUNER_MODULE *pTuner, - int *pTunerType - ); - -int -mxl5005s_GetDeviceAddr( - TUNER_MODULE *pTuner, - unsigned char *pDeviceAddr - ); - -int -mxl5005s_Initialize( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner - ); - -int -mxl5005s_SetRfFreqHz( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - unsigned long RfFreqHz - ); - -int -mxl5005s_GetRfFreqHz( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - unsigned long *pRfFreqHz - ); - - - - - -// Extra manipulaing functions -int -mxl5005s_SetRegsWithTable( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - unsigned char *pAddrTable, - unsigned char *pByteTable, - int TableLen - ); - -int -mxl5005s_SetRegMaskBits( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - unsigned char RegAddr, - unsigned char Msb, - unsigned char Lsb, - const unsigned char WritingValue - ); - -int -mxl5005s_SetSpectrumMode( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - int SpectrumMode - ); - -int -mxl5005s_SetBandwidthHz( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - unsigned long BandwidthHz - ); - - - - - -// I2C birdge module demod argument setting -void -mxl5005s_SetI2cBridgeModuleTunerArg( - TUNER_MODULE *pTuner - ); - - - - - - - - - - - - - - - -#endif +#endif /* __MXL5005S_H */ -- cgit v1.1 From a8214d48e6d41f3a16c1023ca4f30bbd140ba756 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 1 May 2008 05:02:58 -0300 Subject: V4L/DVB (7865): mxl5005s: Cleanup #2 Cleanup #2 Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 907 ++++++++++----------------------- 1 file changed, 271 insertions(+), 636 deletions(-) diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index 3c43306..2af14de 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -22,71 +22,10 @@ * Revision: 080314 - original version */ - -/** - -@file - -@brief MxL5005S tuner module definition - -One can manipulate MxL5005S tuner through MxL5005S module. -MxL5005S module is derived from tuner module. - -*/ - - #include "mxl5005s.h" -/** - -@defgroup MXL5005S_TUNER_MODULE MxL5005S tuner module - -MxL5005S tuner module is drived from tuner base module. - -@see TUNER_BASE_MODULE - -*/ - - - - - -/** -@defgroup MXL5005S_MODULE_BUILDER MxL5005S module builder -@ingroup MXL5005S_TUNER_MODULE - -One should call MxL5005S module builder before using MxL5005S module. - -*/ -/// @{ - - - - - -/** - -@brief MxL5005S tuner module builder - -Use BuildMxl5005sModule() to build MxL5005S module, set all module function pointers with the corresponding functions, -and initialize module private variables. - - -@param [in] ppTuner Pointer to MxL5005S tuner module pointer -@param [in] pTunerModuleMemory Pointer to an allocated tuner module memory -@param [in] pMxl5005sExtraModuleMemory Pointer to an allocated MxL5005S extra module memory -@param [in] pI2cBridgeModuleMemory Pointer to an allocated I2C bridge module memory -@param [in] DeviceAddr MxL5005S I2C device address -@param [in] CrystalFreqHz MxL5005S crystal frequency in Hz - - -@note \n - -# One should call BuildMxl5005sModule() to build MxL5005S module before using it. - -*/ -void -BuildMxl5005sModule( +void BuildMxl5005sModule( TUNER_MODULE **ppTuner, TUNER_MODULE *pTunerModuleMemory, MXL5005S_EXTRA_MODULE *pMxl5005sExtraModuleMemory, @@ -200,43 +139,7 @@ BuildMxl5005sModule( return; } - - - - -/// @} - - - - - -/** - -@defgroup MXL5005S_MANIPULATING_FUNCTIONS MxL5005S manipulating functions derived from tuner base module -@ingroup MXL5005S_TUNER_MODULE - -One can use the MxL5005S tuner module manipulating interface implemented by MxL5005S manipulating functions to -manipulate MxL5005S tuner. - -*/ -/// @{ - - - - - -/** - -@brief Set MxL5005S tuner I2C device address. - -@note \n - -# MxL5005S tuner builder will set TUNER_FP_SET_DEVICE_ADDR() function pointer with mxl5005s_SetDeviceAddr(). - -@see TUNER_FP_SET_DEVICE_ADDR - -*/ -void -mxl5005s_SetDeviceAddr( +void mxl5005s_SetDeviceAddr( TUNER_MODULE *pTuner, unsigned char DeviceAddr ) @@ -249,22 +152,7 @@ mxl5005s_SetDeviceAddr( return; } - - - - -/** - -@brief Get MxL5005S tuner type. - -@note \n - -# MxL5005S tuner builder will set TUNER_FP_GET_TUNER_TYPE() function pointer with mxl5005s_GetTunerType(). - -@see TUNER_FP_GET_TUNER_TYPE - -*/ -void -mxl5005s_GetTunerType( +void mxl5005s_GetTunerType( TUNER_MODULE *pTuner, int *pTunerType ) @@ -276,22 +164,7 @@ mxl5005s_GetTunerType( return; } - - - - -/** - -@brief Get MxL5005S tuner I2C device address. - -@note \n - -# MxL5005S tuner builder will set TUNER_FP_GET_DEVICE_ADDR() function pointer with mxl5005s_GetDeviceAddr(). - -@see TUNER_FP_GET_DEVICE_ADDR - -*/ -int -mxl5005s_GetDeviceAddr( +int mxl5005s_GetDeviceAddr( TUNER_MODULE *pTuner, unsigned char *pDeviceAddr ) @@ -310,22 +183,7 @@ error_status_get_tuner_i2c_device_addr: return FUNCTION_ERROR; } - - - - -/** - -@brief Initialize MxL5005S tuner. - -@note \n - -# MxL5005S tuner builder will set TUNER_FP_INITIALIZE() function pointer with mxl5005s_Initialize(). - -@see TUNER_FP_INITIALIZE - -*/ -int -mxl5005s_Initialize( +int mxl5005s_Initialize( struct dvb_usb_device* dib, TUNER_MODULE *pTuner ) @@ -337,16 +195,12 @@ mxl5005s_Initialize( unsigned char ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; int TableLen; - - // Get tuner extra module. pExtra = (MXL5005S_EXTRA_MODULE *)pTuner->pExtra; - // Get AGC master byte AgcMasterByte = pExtra->AgcMasterByte; - // Initialize MxL5005S tuner according to MxL5005S tuner example code. // Tuner initialization stage 0 @@ -357,37 +211,19 @@ mxl5005s_Initialize( if(pExtra->SetRegsWithTable( dib,pTuner, AddrTable, ByteTable, LEN_1_BYTE) != FUNCTION_SUCCESS) goto error_status_set_tuner_registers; - // Tuner initialization stage 1 MXL_GetInitRegister(&pExtra->MxlDefinedTunerStructure, AddrTable, ByteTable, &TableLen); if(pExtra->SetRegsWithTable( dib,pTuner, AddrTable, ByteTable, TableLen) != FUNCTION_SUCCESS) goto error_status_set_tuner_registers; - return FUNCTION_SUCCESS; - error_status_set_tuner_registers: return FUNCTION_ERROR; } - - - - -/** - -@brief Set MxL5005S tuner RF frequency in Hz. - -@note \n - -# MxL5005S tuner builder will set TUNER_FP_SET_RF_FREQ_HZ() function pointer with mxl5005s_SetRfFreqHz(). - -@see TUNER_FP_SET_RF_FREQ_HZ - -*/ -int -mxl5005s_SetRfFreqHz( +int mxl5005s_SetRfFreqHz( struct dvb_usb_device* dib, TUNER_MODULE *pTuner, unsigned long RfFreqHz @@ -404,8 +240,6 @@ mxl5005s_SetRfFreqHz( unsigned long IfDivval; unsigned char MasterControlByte; - - // Get tuner extra module and base interface module. pExtra = (MXL5005S_EXTRA_MODULE *)pTuner->pExtra; pBaseInterface = pTuner->pBaseInterface; @@ -476,22 +310,7 @@ error_status_set_tuner_registers: return FUNCTION_ERROR; } - - - - -/** - -@brief Get MxL5005S tuner RF frequency in Hz. - -@note \n - -# MxL5005S tuner builder will set TUNER_FP_GET_RF_FREQ_HZ() function pointer with mxl5005s_GetRfFreqHz(). - -@see TUNER_FP_GET_RF_FREQ_HZ - -*/ -int -mxl5005s_GetRfFreqHz( +int mxl5005s_GetRfFreqHz( struct dvb_usb_device* dib, TUNER_MODULE *pTuner, unsigned long *pRfFreqHz @@ -511,18 +330,7 @@ error_status_get_tuner_rf_frequency: return FUNCTION_ERROR; } - - - - -/** - -@brief Set MxL5005S tuner registers with table. - -*/ -/* -int -mxl5005s_SetRegsWithTable( +int mxl5005s_SetRegsWithTable( struct dvb_usb_device* dib, TUNER_MODULE *pTuner, unsigned char *pAddrTable, @@ -585,11 +393,8 @@ mxl5005s_SetRegsWithTable( error_status_set_tuner_registers: return FUNCTION_ERROR; } -*/ - -int -mxl5005s_SetRegsWithTable( +int mxl5005s_SetRegsWithTable( struct dvb_usb_device* dib, TUNER_MODULE *pTuner, unsigned char *pAddrTable, @@ -618,17 +423,7 @@ mxl5005s_SetRegsWithTable( return FUNCTION_SUCCESS; } - - - - -/** - -@brief Set MxL5005S tuner register bits. - -*/ -int -mxl5005s_SetRegMaskBits( +int mxl5005s_SetRegMaskBits( struct dvb_usb_device* dib, TUNER_MODULE *pTuner, unsigned char RegAddr, @@ -685,17 +480,7 @@ error_status_set_tuner_registers: return FUNCTION_ERROR; } - - - - -/** - -@brief Set MxL5005S tuner spectrum mode. - -*/ -int -mxl5005s_SetSpectrumMode( +int mxl5005s_SetSpectrumMode( struct dvb_usb_device* dib, TUNER_MODULE *pTuner, int SpectrumMode @@ -730,17 +515,7 @@ error_status_set_tuner_registers: return FUNCTION_ERROR; } - - - - -/** - -@brief Set MxL5005S tuner bandwidth in Hz. - -*/ -int -mxl5005s_SetBandwidthHz( +int mxl5005s_SetBandwidthHz( struct dvb_usb_device* dib, TUNER_MODULE *pTuner, unsigned long BandwidthHz @@ -777,48 +552,7 @@ error_status_set_tuner_registers: return FUNCTION_ERROR; } - - - - -/// @} - - - - - -/** - -@defgroup MXL5005S_DEPENDENCE MxL5005S dependence -@ingroup MXL5005S_TUNER_MODULE - -MxL5005S dependence is the related functions for MxL5005S tuner module interface. -One should not use MxL5005S dependence directly. - -*/ -/// @{ - - - - - -/** - -@brief Set I2C bridge module tuner arguments. - -MxL5005S builder will use mxl5005s_SetI2cBridgeModuleTunerArg() to set I2C bridge module tuner arguments. - - -@param [in] pTuner The tuner module pointer - - -@see BuildMxl5005sModule() - -*/ -void -mxl5005s_SetI2cBridgeModuleTunerArg( - TUNER_MODULE *pTuner - ) +void mxl5005s_SetI2cBridgeModuleTunerArg(TUNER_MODULE *pTuner) { I2C_BRIDGE_MODULE *pI2cBridge; @@ -834,50 +568,9 @@ mxl5005s_SetI2cBridgeModuleTunerArg( return; } - - - - -/// @} - - - - - - - - - - - - - - - - - - - - - - - // The following context is source code provided by MaxLinear. - - - - - // MaxLinear source code - MXL5005_Initialize.cpp - - - -//#ifdef _MXL_HEADER -//#include "stdafx.h" -//#endif -//#include "MXL5005_c.h" - -_u16 MXL5005_RegisterInit (Tuner_struct * Tuner) +u16 MXL5005_RegisterInit(Tuner_struct *Tuner) { Tuner->TunerRegs_Num = TUNER_REGS_NUM ; // Tuner->TunerRegs = (TunerReg_struct *) calloc( TUNER_REGS_NUM, sizeof(TunerReg_struct) ) ; @@ -1197,7 +890,7 @@ _u16 MXL5005_RegisterInit (Tuner_struct * Tuner) return 0 ; } -_u16 MXL5005_ControlInit (Tuner_struct *Tuner) +u16 MXL5005_ControlInit(Tuner_struct *Tuner) { Tuner->Init_Ctrl_Num = INITCTRL_NUM ; @@ -2136,34 +1829,10 @@ _u16 MXL5005_ControlInit (Tuner_struct *Tuner) return 0 ; } - - - - - - - - - - - - - - // MaxLinear source code - MXL5005_c.cpp - - - // MXL5005.cpp : Defines the initialization routines for the DLL. // 2.6.12 - -//#ifdef _MXL_HEADER -//#include "stdafx.h" -//#endif -//#include "MXL5005_c.h" - - void InitTunerControls(Tuner_struct *Tuner) { MXL5005_RegisterInit(Tuner) ; @@ -2173,8 +1842,6 @@ void InitTunerControls(Tuner_struct *Tuner) #endif } - - /////////////////////////////////////////////////////////////////////////////// // // // Function: MXL_ConfigTuner // @@ -2184,7 +1851,7 @@ void InitTunerControls(Tuner_struct *Tuner) // // // // // Functions used: // -// MXL_SynthIFLO_Calc // +// MXL_SynthIFLO_Calc // // // // Inputs: // // Tuner_struct: structure defined at higher level // @@ -2193,12 +1860,12 @@ void InitTunerControls(Tuner_struct *Tuner) // Bandwidth: Filter Channel Bandwidth (in Hz) // // IF_out: Desired IF out Frequency (in Hz) // // Fxtal: Crystal Frerquency (in Hz) // -// TOP: 0: Dual AGC; Value: take over point // -// IF_OUT_LOAD: IF out load resistor (200/300 Ohms) // -// CLOCK_OUT: 0: Turn off clock out; 1: turn on clock out // -// DIV_OUT: 0: Div-1; 1: Div-4 // -// CAPSELECT: 0: Disable On-chip pulling cap; 1: Enable // -// EN_RSSI: 0: Disable RSSI; 1: Enable RSSI // +// TOP: 0: Dual AGC; Value: take over point // +// IF_OUT_LOAD: IF out load resistor (200/300 Ohms) // +// CLOCK_OUT: 0: Turn off clock out; 1: turn on clock out // +// DIV_OUT: 0: Div-1; 1: Div-4 // +// CAPSELECT: 0: Disable On-chip pulling cap; 1: Enable // +// EN_RSSI: 0: Disable RSSI; 1: Enable RSSI // // // // Outputs: // // Tuner // @@ -2208,26 +1875,26 @@ void InitTunerControls(Tuner_struct *Tuner) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -_u16 MXL5005_TunerConfig(Tuner_struct *Tuner, - _u8 Mode, // 0: Analog Mode ; 1: Digital Mode - _u8 IF_mode, // for Analog Mode, 0: zero IF; 1: low IF - _u32 Bandwidth, // filter channel bandwidth (6, 7, 8) - _u32 IF_out, // Desired IF Out Frequency - _u32 Fxtal, // XTAL Frequency - _u8 AGC_Mode, // AGC Mode - Dual AGC: 0, Single AGC: 1 - _u16 TOP, // 0: Dual AGC; Value: take over point - _u16 IF_OUT_LOAD, // IF Out Load Resistor (200 / 300 Ohms) - _u8 CLOCK_OUT, // 0: turn off clock out; 1: turn on clock out - _u8 DIV_OUT, // 0: Div-1; 1: Div-4 - _u8 CAPSELECT, // 0: disable On-Chip pulling cap; 1: enable - _u8 EN_RSSI, // 0: disable RSSI; 1: enable RSSI - _u8 Mod_Type, // Modulation Type; - // 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable - _u8 TF_Type // Tracking Filter - // 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H +u16 MXL5005_TunerConfig(Tuner_struct *Tuner, + u8 Mode, // 0: Analog Mode ; 1: Digital Mode + u8 IF_mode, // for Analog Mode, 0: zero IF; 1: low IF + u32 Bandwidth, // filter channel bandwidth (6, 7, 8) + u32 IF_out, // Desired IF Out Frequency + u32 Fxtal, // XTAL Frequency + u8 AGC_Mode, // AGC Mode - Dual AGC: 0, Single AGC: 1 + u16 TOP, // 0: Dual AGC; Value: take over point + u16 IF_OUT_LOAD, // IF Out Load Resistor (200 / 300 Ohms) + u8 CLOCK_OUT, // 0: turn off clock out; 1: turn on clock out + u8 DIV_OUT, // 0: Div-1; 1: Div-4 + u8 CAPSELECT, // 0: disable On-Chip pulling cap; 1: enable + u8 EN_RSSI, // 0: disable RSSI; 1: enable RSSI + u8 Mod_Type, // Modulation Type; + // 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable + u8 TF_Type // Tracking Filter + // 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H ) { - _u16 status = 0 ; + u16 status = 0 ; Tuner->Mode = Mode ; Tuner->IF_Mode = IF_mode ; @@ -2244,15 +1911,10 @@ _u16 MXL5005_TunerConfig(Tuner_struct *Tuner, Tuner->Mod_Type = Mod_Type ; Tuner->TF_Type = TF_Type ; - - - // - // Initialize all the controls and registers - // + /* Initialize all the controls and registers */ InitTunerControls (Tuner) ; - // - // Synthesizer LO frequency calculation - // + + /* Synthesizer LO frequency calculation */ MXL_SynthIFLO_Calc( Tuner ) ; return status ; @@ -2366,9 +2028,9 @@ void MXL_SynthRFTGLO_Calc(Tuner_struct *Tuner) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -_u16 MXL_OverwriteICDefault( Tuner_struct *Tuner) +u16 MXL_OverwriteICDefault( Tuner_struct *Tuner) { - _u16 status = 0 ; + u16 status = 0 ; status += MXL_ControlWrite(Tuner, OVERRIDE_1, 1) ; status += MXL_ControlWrite(Tuner, OVERRIDE_2, 1) ; @@ -2403,20 +2065,20 @@ _u16 MXL_OverwriteICDefault( Tuner_struct *Tuner) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -_u16 MXL_BlockInit( Tuner_struct *Tuner ) +u16 MXL_BlockInit( Tuner_struct *Tuner ) { - _u16 status = 0 ; + u16 status = 0 ; status += MXL_OverwriteICDefault(Tuner) ; // // Downconverter Control - // Dig Ana + // Dig Ana status += MXL_ControlWrite(Tuner, DN_IQTN_AMP_CUT, Tuner->Mode ? 1 : 0) ; // // Filter Control - // Dig Ana + // Dig Ana status += MXL_ControlWrite(Tuner, BB_MODE, Tuner->Mode ? 0 : 1) ; status += MXL_ControlWrite(Tuner, BB_BUF, Tuner->Mode ? 3 : 2) ; status += MXL_ControlWrite(Tuner, BB_BUF_OA, Tuner->Mode ? 1 : 0) ; @@ -2439,7 +2101,7 @@ _u16 MXL_BlockInit( Tuner_struct *Tuner ) } } else { // Analog Mode switch (Tuner->Chan_Bandwidth) { - case 8000000: // Low Zero + case 8000000: // Low Zero status += MXL_ControlWrite(Tuner, BB_ALPF_BANDSELECT, (Tuner->IF_Mode ? 0 : 3)) ; break ; case 7000000: @@ -2453,7 +2115,7 @@ _u16 MXL_BlockInit( Tuner_struct *Tuner ) // // Charge Pump Control - // Dig Ana + // Dig Ana status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, Tuner->Mode ? 5 : 8) ; status += MXL_ControlWrite(Tuner, RFSYN_EN_CHP_HIGAIN, Tuner->Mode ? 1 : 1) ; status += MXL_ControlWrite(Tuner, EN_CHP_LIN_B, Tuner->Mode ? 0 : 0) ; @@ -2621,8 +2283,6 @@ _u16 MXL_BlockInit( Tuner_struct *Tuner ) // Apply Default value to BB_INITSTATE_DLPF_TUNE // - - // // RSSI Control // @@ -2697,7 +2357,7 @@ _u16 MXL_BlockInit( Tuner_struct *Tuner ) //Tuner->AGC_Mode = 1 ; // Single AGC Mode - // Disable RSSI //change here for v2.6.5 + // Disable RSSI //change here for v2.6.5 status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 0) ; @@ -2787,13 +2447,13 @@ _u16 MXL_BlockInit( Tuner_struct *Tuner ) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -_u16 MXL_IFSynthInit( Tuner_struct * Tuner ) +u16 MXL_IFSynthInit(Tuner_struct * Tuner) { - _u16 status = 0 ; + u16 status = 0 ; // Declare Local Variables - _u32 Fref = 0 ; - _u32 Kdbl, intModVal ; - _u32 fracModVal ; + u32 Fref = 0 ; + u32 Kdbl, intModVal ; + u32 fracModVal ; Kdbl = 2 ; if (Tuner->Fxtal >= 12000000UL && Tuner->Fxtal <= 16000000UL) @@ -2999,8 +2659,6 @@ _u16 MXL_IFSynthInit( Tuner_struct * Tuner ) fracModVal = fracModVal / ((Tuner->Fxtal * Kdbl/2)/1000) ; status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_IF, fracModVal) ; - - return status ; } @@ -3008,14 +2666,14 @@ _u16 MXL_IFSynthInit( Tuner_struct * Tuner ) // // // Function: MXL_GetXtalInt // // // -// Description: return the Crystal Integration Value for // -// TG_VCO_BIAS calculation // +// Description: return the Crystal Integration Value for // +// TG_VCO_BIAS calculation // // // // Globals: // // NONE // // // // Functions used: // -// NONE // +// NONE // // // // Inputs: // // Crystal Frequency Value in Hz // @@ -3028,7 +2686,7 @@ _u16 MXL_IFSynthInit( Tuner_struct * Tuner ) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -_u32 MXL_GetXtalInt(_u32 Xtal_Freq) +u32 MXL_GetXtalInt(u32 Xtal_Freq) { if ((Xtal_Freq % 1000000) == 0) return (Xtal_Freq / 10000) ; @@ -3048,7 +2706,7 @@ _u32 MXL_GetXtalInt(_u32 Xtal_Freq) // Functions used: // // MXL_SynthRFTGLO_Calc // // MXL5005_ControlWrite // -// MXL_GetXtalInt // +// MXL_GetXtalInt // // // // Inputs: // // Tuner : Tuner structure defined at higher level // @@ -3060,20 +2718,20 @@ _u32 MXL_GetXtalInt(_u32 Xtal_Freq) // 0 : Successful // // 1 : Unsuccessful // /////////////////////////////////////////////////////////////////////////////// -_u16 MXL_TuneRF(Tuner_struct *Tuner, _u32 RF_Freq) +u16 MXL_TuneRF(Tuner_struct *Tuner, u32 RF_Freq) { // Declare Local Variables - _u16 status = 0 ; - _u32 divider_val, E3, E4, E5, E5A ; - _u32 Fmax, Fmin, FmaxBin, FminBin ; - _u32 Kdbl_RF = 2; - _u32 tg_divval ; - _u32 tg_lo ; - _u32 Xtal_Int ; + u16 status = 0 ; + u32 divider_val, E3, E4, E5, E5A ; + u32 Fmax, Fmin, FmaxBin, FminBin ; + u32 Kdbl_RF = 2; + u32 tg_divval ; + u32 tg_lo ; + u32 Xtal_Int ; - _u32 Fref_TG; - _u32 Fvco; -// _u32 temp; + u32 Fref_TG; + u32 Fvco; +// u32 temp; Xtal_Int = MXL_GetXtalInt(Tuner->Fxtal ) ; @@ -3774,7 +3432,8 @@ _u16 MXL_TuneRF(Tuner_struct *Tuner, _u32 RF_Freq) { status += MXL_ControlWrite(Tuner, DAC_DIN_A, 0) ; - if (Tuner->RF_IN >= 471000000 && (Tuner->RF_IN - 471000000)%6000000 != 0) // if UHF and terrestrial => Turn off Tracking Filter + // if UHF and terrestrial => Turn off Tracking Filter + if (Tuner->RF_IN >= 471000000 && (Tuner->RF_IN - 471000000)%6000000 != 0) { // Turn off all the banks status += MXL_SetGPIO(Tuner, 3, 1) ; @@ -4089,7 +3748,8 @@ _u16 MXL_TuneRF(Tuner_struct *Tuner, _u32 RF_Freq) { status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; - if (Tuner->RF_IN >= 471000000 && (Tuner->RF_IN - 471000000)%6000000 != 0) //if UHF and terrestrial=> Turn off Tracking Filter + // if UHF and terrestrial=> Turn off Tracking Filter + if (Tuner->RF_IN >= 471000000 && (Tuner->RF_IN - 471000000)%6000000 != 0) { // Turn off all the banks status += MXL_SetGPIO(Tuner, 3, 1) ; @@ -4181,9 +3841,9 @@ _u16 MXL_TuneRF(Tuner_struct *Tuner, _u32 RF_Freq) return status ; } -_u16 MXL_SetGPIO(Tuner_struct *Tuner, _u8 GPIO_Num, _u8 GPIO_Val) +u16 MXL_SetGPIO(Tuner_struct *Tuner, u8 GPIO_Num, u8 GPIO_Val) { - _u16 status = 0 ; + u16 status = 0 ; if (GPIO_Num == 1) status += MXL_ControlWrite(Tuner, GPIO_1B, GPIO_Val ? 0 : 1) ; @@ -4247,9 +3907,9 @@ _u16 MXL_SetGPIO(Tuner_struct *Tuner, _u8 GPIO_Num, _u8 GPIO_Val) // >0 : Value exceed maximum allowed for control number // // // /////////////////////////////////////////////////////////////////////////////// -_u16 MXL_ControlWrite(Tuner_struct *Tuner, _u16 ControlNum, _u32 value) +u16 MXL_ControlWrite(Tuner_struct *Tuner, u16 ControlNum, u32 value) { - _u16 status = 0 ; + u16 status = 0 ; // Will write ALL Matching Control Name status += MXL_ControlWrite_Group( Tuner, ControlNum, value, 1 ) ; // Write Matching INIT Control status += MXL_ControlWrite_Group( Tuner, ControlNum, value, 2 ) ; // Write Matching CH Control @@ -4287,11 +3947,11 @@ _u16 MXL_ControlWrite(Tuner_struct *Tuner, _u16 ControlNum, _u32 value) // 2 : Control name not found // // // /////////////////////////////////////////////////////////////////////////////// -_u16 MXL_ControlWrite_Group(Tuner_struct *Tuner, _u16 controlNum, _u32 value, _u16 controlGroup) +u16 MXL_ControlWrite_Group(Tuner_struct *Tuner, u16 controlNum, u32 value, u16 controlGroup) { - _u16 i, j, k ; - _u32 highLimit ; - _u32 ctrlVal ; + u16 i, j, k ; + u32 highLimit ; + u32 ctrlVal ; if( controlGroup == 1) // Initial Control { @@ -4304,11 +3964,11 @@ _u16 MXL_ControlWrite_Group(Tuner_struct *Tuner, _u16 controlNum, _u32 value, _u { for( j=0; jInit_Ctrl[i].size; j++) { - Tuner->Init_Ctrl[i].val[j] = (_u8)((value >> j) & 0x01) ; + Tuner->Init_Ctrl[i].val[j] = (u8)((value >> j) & 0x01) ; // change the register map accordingly - MXL_RegWriteBit( Tuner, (_u8)(Tuner->Init_Ctrl[i].addr[j]), - (_u8)(Tuner->Init_Ctrl[i].bit[j]), - (_u8)((value>>j) & 0x01) ) ; + MXL_RegWriteBit( Tuner, (u8)(Tuner->Init_Ctrl[i].addr[j]), + (u8)(Tuner->Init_Ctrl[i].bit[j]), + (u8)((value>>j) & 0x01) ) ; } ctrlVal = 0 ; for(k=0; kInit_Ctrl[i].size; k++) @@ -4334,11 +3994,11 @@ _u16 MXL_ControlWrite_Group(Tuner_struct *Tuner, _u16 controlNum, _u32 value, _u { for( j=0; jCH_Ctrl[i].size; j++) { - Tuner->CH_Ctrl[i].val[j] = (_u8)((value >> j) & 0x01) ; + Tuner->CH_Ctrl[i].val[j] = (u8)((value >> j) & 0x01) ; // change the register map accordingly - MXL_RegWriteBit( Tuner, (_u8)(Tuner->CH_Ctrl[i].addr[j]), - (_u8)(Tuner->CH_Ctrl[i].bit[j]), - (_u8)((value>>j) & 0x01) ) ; + MXL_RegWriteBit( Tuner, (u8)(Tuner->CH_Ctrl[i].addr[j]), + (u8)(Tuner->CH_Ctrl[i].bit[j]), + (u8)((value>>j) & 0x01) ) ; } ctrlVal = 0 ; for(k=0; kCH_Ctrl[i].size; k++) @@ -4365,11 +4025,11 @@ _u16 MXL_ControlWrite_Group(Tuner_struct *Tuner, _u16 controlNum, _u32 value, _u { for( j=0; jMXL_Ctrl[i].size; j++) { - Tuner->MXL_Ctrl[i].val[j] = (_u8)((value >> j) & 0x01) ; + Tuner->MXL_Ctrl[i].val[j] = (u8)((value >> j) & 0x01) ; // change the register map accordingly - MXL_RegWriteBit( Tuner, (_u8)(Tuner->MXL_Ctrl[i].addr[j]), - (_u8)(Tuner->MXL_Ctrl[i].bit[j]), - (_u8)((value>>j) & 0x01) ) ; + MXL_RegWriteBit( Tuner, (u8)(Tuner->MXL_Ctrl[i].addr[j]), + (u8)(Tuner->MXL_Ctrl[i].bit[j]), + (u8)((value>>j) & 0x01) ) ; } ctrlVal = 0 ; for(k=0; kMXL_Ctrl[i].size; k++) @@ -4413,7 +4073,7 @@ _u16 MXL_ControlWrite_Group(Tuner_struct *Tuner, _u16 controlNum, _u32 value, _u // -1 : Invalid Register Address // // // /////////////////////////////////////////////////////////////////////////////// -_u16 MXL_RegWrite(Tuner_struct *Tuner, _u8 RegNum, _u8 RegVal) +u16 MXL_RegWrite(Tuner_struct *Tuner, u8 RegNum, u8 RegVal) { int i ; @@ -4453,7 +4113,7 @@ _u16 MXL_RegWrite(Tuner_struct *Tuner, _u8 RegNum, _u8 RegVal) // -1 : Invalid Register Address // // // /////////////////////////////////////////////////////////////////////////////// -_u16 MXL_RegRead(Tuner_struct *Tuner, _u8 RegNum, _u8 *RegVal) +u16 MXL_RegRead(Tuner_struct *Tuner, u8 RegNum, u8 *RegVal) { int i ; @@ -4461,7 +4121,7 @@ _u16 MXL_RegRead(Tuner_struct *Tuner, _u8 RegNum, _u8 *RegVal) { if (RegNum == Tuner->TunerRegs[i].Reg_Num ) { - *RegVal = (_u8)(Tuner->TunerRegs[i].Reg_Val) ; + *RegVal = (u8)(Tuner->TunerRegs[i].Reg_Val) ; return 0 ; } } @@ -4490,10 +4150,10 @@ _u16 MXL_RegRead(Tuner_struct *Tuner, _u8 RegNum, _u8 *RegVal) // -1 : Invalid control name // // // /////////////////////////////////////////////////////////////////////////////// -_u16 MXL_ControlRead(Tuner_struct *Tuner, _u16 controlNum, _u32 * value) +u16 MXL_ControlRead(Tuner_struct *Tuner, u16 controlNum, u32 * value) { - _u32 ctrlVal ; - _u16 i, k ; + u32 ctrlVal ; + u16 i, k ; for (i=0; iInit_Ctrl_Num ; i++) { @@ -4539,7 +4199,7 @@ _u16 MXL_ControlRead(Tuner_struct *Tuner, _u16 controlNum, _u32 * value) // Function: MXL_ControlRegRead // // // // Description: Retrieve the register addresses and count related to a // -// a specific control name // +// a specific control name // // // // Globals: // // NONE // @@ -4550,24 +4210,24 @@ _u16 MXL_ControlRead(Tuner_struct *Tuner, _u16 controlNum, _u32 * value) // // // Outputs: // // RegNum : returned register address array // -// count : returned register count related to a control // +// count : returned register count related to a control // // // // Return: // // 0 : Successful read // // -1 : Invalid control name // // // /////////////////////////////////////////////////////////////////////////////// -_u16 MXL_ControlRegRead(Tuner_struct *Tuner, _u16 controlNum, _u8 *RegNum, int * count) +u16 MXL_ControlRegRead(Tuner_struct *Tuner, u16 controlNum, u8 *RegNum, int * count) { - _u16 i, j, k ; - _u16 Count ; + u16 i, j, k ; + u16 Count ; for (i=0; iInit_Ctrl_Num ; i++) { if ( controlNum == Tuner->Init_Ctrl[i].Ctrl_Num ) { Count = 1 ; - RegNum[0] = (_u8)(Tuner->Init_Ctrl[i].addr[0]) ; + RegNum[0] = (u8)(Tuner->Init_Ctrl[i].addr[0]) ; for(k=1; kInit_Ctrl[i].size; k++) { @@ -4576,7 +4236,7 @@ _u16 MXL_ControlRegRead(Tuner_struct *Tuner, _u16 controlNum, _u8 *RegNum, int * if (Tuner->Init_Ctrl[i].addr[k] != RegNum[j]) { Count ++ ; - RegNum[Count-1] = (_u8)(Tuner->Init_Ctrl[i].addr[k]) ; + RegNum[Count-1] = (u8)(Tuner->Init_Ctrl[i].addr[k]) ; } } @@ -4590,7 +4250,7 @@ _u16 MXL_ControlRegRead(Tuner_struct *Tuner, _u16 controlNum, _u8 *RegNum, int * if ( controlNum == Tuner->CH_Ctrl[i].Ctrl_Num ) { Count = 1 ; - RegNum[0] = (_u8)(Tuner->CH_Ctrl[i].addr[0]) ; + RegNum[0] = (u8)(Tuner->CH_Ctrl[i].addr[0]) ; for(k=1; kCH_Ctrl[i].size; k++) { @@ -4599,7 +4259,7 @@ _u16 MXL_ControlRegRead(Tuner_struct *Tuner, _u16 controlNum, _u8 *RegNum, int * if (Tuner->CH_Ctrl[i].addr[k] != RegNum[j]) { Count ++ ; - RegNum[Count-1] = (_u8)(Tuner->CH_Ctrl[i].addr[k]) ; + RegNum[Count-1] = (u8)(Tuner->CH_Ctrl[i].addr[k]) ; } } } @@ -4613,7 +4273,7 @@ _u16 MXL_ControlRegRead(Tuner_struct *Tuner, _u16 controlNum, _u8 *RegNum, int * if ( controlNum == Tuner->MXL_Ctrl[i].Ctrl_Num ) { Count = 1 ; - RegNum[0] = (_u8)(Tuner->MXL_Ctrl[i].addr[0]) ; + RegNum[0] = (u8)(Tuner->MXL_Ctrl[i].addr[0]) ; for(k=1; kMXL_Ctrl[i].size; k++) { @@ -4622,7 +4282,7 @@ _u16 MXL_ControlRegRead(Tuner_struct *Tuner, _u16 controlNum, _u8 *RegNum, int * if (Tuner->MXL_Ctrl[i].addr[k] != RegNum[j]) { Count ++ ; - RegNum[Count-1] = (_u8)Tuner->MXL_Ctrl[i].addr[k] ; + RegNum[Count-1] = (u8)Tuner->MXL_Ctrl[i].addr[k] ; } } } @@ -4648,8 +4308,8 @@ _u16 MXL_ControlRegRead(Tuner_struct *Tuner, _u16 controlNum, _u8 *RegNum, int * // Inputs: // // Tuner_struct : structure defined at higher level // // address : register address // -// bit : register bit number // -// bitVal : register bit value // +// bit : register bit number // +// bitVal : register bit value // // // // Outputs: // // NONE // @@ -4659,16 +4319,16 @@ _u16 MXL_ControlRegRead(Tuner_struct *Tuner, _u16 controlNum, _u8 *RegNum, int * // // /////////////////////////////////////////////////////////////////////////////// -void MXL_RegWriteBit(Tuner_struct *Tuner, _u8 address, _u8 bit, _u8 bitVal) +void MXL_RegWriteBit(Tuner_struct *Tuner, u8 address, u8 bit, u8 bitVal) { int i ; // Declare Local Constants - const _u8 AND_MAP[8] = { + const u8 AND_MAP[8] = { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F } ; - const _u8 OR_MAP[8] = { + const u8 OR_MAP[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 } ; @@ -4707,7 +4367,7 @@ void MXL_RegWriteBit(Tuner_struct *Tuner, _u8 address, _u8 bit, _u8 bitVal) // Computed value // // // /////////////////////////////////////////////////////////////////////////////// -_u32 MXL_Ceiling( _u32 value, _u32 resolution ) +u32 MXL_Ceiling( u32 value, u32 resolution ) { return (value/resolution + (value%resolution > 0 ? 1 : 0)) ; }; @@ -4715,15 +4375,15 @@ _u32 MXL_Ceiling( _u32 value, _u32 resolution ) // // Retrieve the Initialzation Registers // -_u16 MXL_GetInitRegister(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) +u16 MXL_GetInitRegister(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count) { - _u16 status = 0; + u16 status = 0; int i ; - _u8 RegAddr[] = {11, 12, 13, 22, 32, 43, 44, 53, 56, 59, 73, + u8 RegAddr[] = {11, 12, 13, 22, 32, 43, 44, 53, 56, 59, 73, 76, 77, 91, 134, 135, 137, 147, 156, 166, 167, 168, 25 } ; - *count = sizeof(RegAddr) / sizeof(_u8) ; + *count = sizeof(RegAddr) / sizeof(u8) ; status += MXL_BlockInit(Tuner) ; @@ -4736,24 +4396,24 @@ _u16 MXL_GetInitRegister(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *co return status ; } -_u16 MXL_GetCHRegister(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) +u16 MXL_GetCHRegister(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count) { - _u16 status = 0; + u16 status = 0; int i ; //add 77, 166, 167, 168 register for 2.6.12 #ifdef _MXL_PRODUCTION - _u8 RegAddr[] = {14, 15, 16, 17, 22, 43, 65, 68, 69, 70, 73, 92, 93, 106, - 107, 108, 109, 110, 111, 112, 136, 138, 149, 77, 166, 167, 168 } ; + u8 RegAddr[] = {14, 15, 16, 17, 22, 43, 65, 68, 69, 70, 73, 92, 93, 106, + 107, 108, 109, 110, 111, 112, 136, 138, 149, 77, 166, 167, 168 } ; #else - _u8 RegAddr[] = {14, 15, 16, 17, 22, 43, 68, 69, 70, 73, 92, 93, 106, - 107, 108, 109, 110, 111, 112, 136, 138, 149, 77, 166, 167, 168 } ; - //_u8 RegAddr[171]; + u8 RegAddr[] = {14, 15, 16, 17, 22, 43, 68, 69, 70, 73, 92, 93, 106, + 107, 108, 109, 110, 111, 112, 136, 138, 149, 77, 166, 167, 168 } ; + //u8 RegAddr[171]; //for (i=0; i<=170; i++) // RegAddr[i] = i; #endif - *count = sizeof(RegAddr) / sizeof(_u8) ; + *count = sizeof(RegAddr) / sizeof(u8) ; for (i=0 ; i< *count; i++) { @@ -4765,14 +4425,14 @@ _u16 MXL_GetCHRegister(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *coun } -_u16 MXL_GetCHRegister_ZeroIF(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) +u16 MXL_GetCHRegister_ZeroIF(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count) { - _u16 status = 0 ; + u16 status = 0 ; int i ; - _u8 RegAddr[] = {43, 136} ; + u8 RegAddr[] = {43, 136} ; - *count = sizeof(RegAddr) / sizeof(_u8) ; + *count = sizeof(RegAddr) / sizeof(u8) ; for (i=0; i<*count; i++) { @@ -4783,14 +4443,14 @@ _u16 MXL_GetCHRegister_ZeroIF(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, in } -_u16 MXL_GetCHRegister_LowIF(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int *count) +u16 MXL_GetCHRegister_LowIF(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count) { - _u16 status = 0 ; + u16 status = 0 ; int i ; - _u8 RegAddr[] = {138} ; + u8 RegAddr[] = {138} ; - *count = sizeof(RegAddr) / sizeof(_u8) ; + *count = sizeof(RegAddr) / sizeof(u8) ; for (i=0; i<*count; i++) { @@ -4801,7 +4461,7 @@ _u16 MXL_GetCHRegister_LowIF(Tuner_struct *Tuner, _u8 * RegNum, _u8 *RegVal, int } -_u16 MXL_GetMasterControl(_u8 *MasterReg, int state) +u16 MXL_GetMasterControl(u8 *MasterReg, int state) { if (state == 1) // Load_Start *MasterReg = 0xF3 ; @@ -4816,168 +4476,143 @@ _u16 MXL_GetMasterControl(_u8 *MasterReg, int state) } #ifdef _MXL_PRODUCTION -_u16 MXL_VCORange_Test(Tuner_struct *Tuner, int VCO_Range) -{ - _u16 status = 0 ; - - if (VCO_Range == 1) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1 ) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0 ) ; - if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode - { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 56 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 180224 ) ; - } - if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode - { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 56 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 222822 ) ; - } - if (Tuner->Mode == 1) // Digital Mode - { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 56 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 229376 ) ; - } - } - - if (VCO_Range == 2) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1 ) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 41 ) ; - if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode - { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438 ) ; - } - if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode - { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438 ) ; - } - if (Tuner->Mode == 1) // Digital Mode - { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 41 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 16384 ) ; - } - } - - if (VCO_Range == 3) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1 ) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42 ) ; - if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode - { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 44 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 173670 ) ; - } - if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode - { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 44 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 173670 ) ; - } - if (Tuner->Mode == 1) // Digital Mode - { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 245760 ) ; - } - } - - if (VCO_Range == 4) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1 ) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27 ) ; - if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode - { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438 ) ; - } - if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode - { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438 ) ; - } - if (Tuner->Mode == 1) // Digital Mode - { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 212992 ) ; - } - } - - return status ; -} - -_u16 MXL_Hystersis_Test(Tuner_struct *Tuner, int Hystersis) +u16 MXL_VCORange_Test(Tuner_struct *Tuner, int VCO_Range) { - _u16 status = 0 ; - - if (Hystersis == 1) - status += MXL_ControlWrite(Tuner, DN_BYPASS_AGC_I2C, 1) ; - - return status ; -} -#endif - - - - - - + u16 status = 0 ; + + if (VCO_Range == 1) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1); + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1); + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0); + if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8); + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 56); + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 180224); + } + if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 56 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 222822 ) ; + } + if (Tuner->Mode == 1) // Digital Mode { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 56 ) ; + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 229376 ) ; + } + } + if (VCO_Range == 2) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1); + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1); + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0); + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 41); + if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42); + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438); + } + if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42); + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438); + } + if (Tuner->Mode == 1) // Digital Mode { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 41); + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 16384); + } + } + if (VCO_Range == 3) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1); + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1); + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0); + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8); + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42); + if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8); + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 44); + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 173670); + } + if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8); + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 44); + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 173670); + } + if (Tuner->Mode == 1) // Digital Mode { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8); + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42); + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 245760); + } + } + if (VCO_Range == 4) { + status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1); + status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1); + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0); + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27); + if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27); + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438); + } + if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27); + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438); + } + if (Tuner->Mode == 1) // Digital Mode { + status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27); + status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 212992); + } + } + return status; +} +u16 MXL_Hystersis_Test(Tuner_struct *Tuner, int Hystersis) +{ + u16 status = 0; + if (Hystersis == 1) + status += MXL_ControlWrite(Tuner, DN_BYPASS_AGC_I2C, 1); + return status; +} +#endif -- cgit v1.1 From 3935c25484bc632b12c447e19c4eacbf5de5f7ae Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 1 May 2008 05:45:44 -0300 Subject: V4L/DVB (7866): mxl5005s: Cleanup #3 Cleanup #3 Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 5527 ++++++++++++++++---------------- drivers/media/common/tuners/mxl5005s.h | 165 - 2 files changed, 2677 insertions(+), 3015 deletions(-) diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index 2af14de..d888548 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -24,164 +24,61 @@ #include "mxl5005s.h" - -void BuildMxl5005sModule( - TUNER_MODULE **ppTuner, - TUNER_MODULE *pTunerModuleMemory, - MXL5005S_EXTRA_MODULE *pMxl5005sExtraModuleMemory, - BASE_INTERFACE_MODULE *pBaseInterfaceModuleMemory, - I2C_BRIDGE_MODULE *pI2cBridgeModuleMemory, - unsigned char DeviceAddr, - int StandardMode - ) -{ - MXL5005S_EXTRA_MODULE *pExtra; - - int MxlModMode; - int MxlIfMode; - unsigned long MxlBandwitdh; - unsigned long MxlIfFreqHz; - unsigned long MxlCrystalFreqHz; - int MxlAgcMode; - unsigned short MxlTop; - unsigned short MxlIfOutputLoad; - int MxlClockOut; - int MxlDivOut; - int MxlCapSel; - int MxlRssiOnOff; - unsigned char MxlStandard; - unsigned char MxlTfType; - - - - // Set tuner module pointer, tuner extra module pointer, and I2C bridge module pointer. - *ppTuner = pTunerModuleMemory; - (*ppTuner)->pExtra = pMxl5005sExtraModuleMemory; - (*ppTuner)->pBaseInterface = pBaseInterfaceModuleMemory; - (*ppTuner)->pI2cBridge = pI2cBridgeModuleMemory; - - // Get tuner extra module pointer. - pExtra = (MXL5005S_EXTRA_MODULE *)(*ppTuner)->pExtra; - - - // Set I2C bridge tuner arguments. - mxl5005s_SetI2cBridgeModuleTunerArg(*ppTuner); - - - // Set tuner module manipulating function pointers. - (*ppTuner)->SetDeviceAddr = mxl5005s_SetDeviceAddr; - - (*ppTuner)->GetTunerType = mxl5005s_GetTunerType; - (*ppTuner)->GetDeviceAddr = mxl5005s_GetDeviceAddr; - - (*ppTuner)->Initialize = mxl5005s_Initialize; - (*ppTuner)->SetRfFreqHz = mxl5005s_SetRfFreqHz; - (*ppTuner)->GetRfFreqHz = mxl5005s_GetRfFreqHz; - - - // Set tuner extra module manipulating function pointers. - pExtra->SetRegsWithTable = mxl5005s_SetRegsWithTable; - pExtra->SetRegMaskBits = mxl5005s_SetRegMaskBits; - pExtra->SetSpectrumMode = mxl5005s_SetSpectrumMode; - pExtra->SetBandwidthHz = mxl5005s_SetBandwidthHz; - - - // Initialize tuner parameter setting status. - (*ppTuner)->IsDeviceAddrSet = NO; - (*ppTuner)->IsRfFreqHzSet = NO; - - - // Set MxL5005S parameters. - MxlModMode = MXL_DIGITAL_MODE; - MxlIfMode = MXL_ZERO_IF; - MxlBandwitdh = MXL5005S_BANDWIDTH_8MHZ; - MxlIfFreqHz = IF_FREQ_4570000HZ; - MxlCrystalFreqHz = CRYSTAL_FREQ_16000000HZ; - MxlAgcMode = MXL_SINGLE_AGC; - MxlTop = MXL5005S_TOP_25P2; - MxlIfOutputLoad = MXL5005S_IF_OUTPUT_LOAD_200_OHM; - MxlClockOut = MXL_CLOCK_OUT_DISABLE; - MxlDivOut = MXL_DIV_OUT_4; - MxlCapSel = MXL_CAP_SEL_ENABLE; - MxlRssiOnOff = MXL_RSSI_ENABLE; - MxlTfType = MXL_TF_C_H; - - - // Set MxL5005S parameters according to standard mode - switch(StandardMode) - { - default: - case MXL5005S_STANDARD_DVBT: MxlStandard = MXL_DVBT; break; - case MXL5005S_STANDARD_ATSC: MxlStandard = MXL_ATSC; break; - } - - - // Set MxL5005S extra module. - pExtra->AgcMasterByte = (MxlAgcMode == MXL_DUAL_AGC) ? 0x4 : 0x0; - - MXL5005_TunerConfig(&pExtra->MxlDefinedTunerStructure, (unsigned char)MxlModMode, (unsigned char)MxlIfMode, - MxlBandwitdh, MxlIfFreqHz, MxlCrystalFreqHz, (unsigned char)MxlAgcMode, MxlTop, MxlIfOutputLoad, - (unsigned char)MxlClockOut, (unsigned char)MxlDivOut, (unsigned char)MxlCapSel, (unsigned char)MxlRssiOnOff, - MxlStandard, MxlTfType); - - - - // Note: Need to set all module arguments before using module functions. - - - // Set tuner type. - (*ppTuner)->TunerType = TUNER_TYPE_MXL5005S; - - // Set tuner I2C device address. - (*ppTuner)->SetDeviceAddr(*ppTuner, DeviceAddr); - - - return; -} - -void mxl5005s_SetDeviceAddr( - TUNER_MODULE *pTuner, - unsigned char DeviceAddr - ) -{ - // Set tuner I2C device address. - pTuner->DeviceAddr = DeviceAddr; - pTuner->IsDeviceAddrSet = YES; - - - return; -} - -void mxl5005s_GetTunerType( - TUNER_MODULE *pTuner, - int *pTunerType - ) -{ - // Get tuner type from tuner module. - *pTunerType = pTuner->TunerType; - - - return; -} - -int mxl5005s_GetDeviceAddr( - TUNER_MODULE *pTuner, - unsigned char *pDeviceAddr - ) +/* MXL5005 Tuner Control Struct */ +typedef struct _TunerControl_struct { + u16 Ctrl_Num; /* Control Number */ + u16 size; /* Number of bits to represent Value */ + u16 addr[25]; /* Array of Tuner Register Address for each bit position */ + u16 bit[25]; /* Array of bit position in Register Address for each bit position */ + u16 val[25]; /* Binary representation of Value */ +} TunerControl_struct; + +/* MXL5005 Tuner Struct */ +struct mxl5005s_state { - // Get tuner I2C device address from tuner module. - if(pTuner->IsDeviceAddrSet != YES) - goto error_status_get_tuner_i2c_device_addr; - - *pDeviceAddr = pTuner->DeviceAddr; - - - return FUNCTION_SUCCESS; + u8 Mode; /* 0: Analog Mode ; 1: Digital Mode */ + u8 IF_Mode; /* for Analog Mode, 0: zero IF; 1: low IF */ + u32 Chan_Bandwidth; /* filter channel bandwidth (6, 7, 8) */ + u32 IF_OUT; /* Desired IF Out Frequency */ + u16 IF_OUT_LOAD; /* IF Out Load Resistor (200/300 Ohms) */ + u32 RF_IN; /* RF Input Frequency */ + u32 Fxtal; /* XTAL Frequency */ + u8 AGC_Mode; /* AGC Mode 0: Dual AGC; 1: Single AGC */ + u16 TOP; /* Value: take over point */ + u8 CLOCK_OUT; /* 0: turn off clock out; 1: turn on clock out */ + u8 DIV_OUT; /* 4MHz or 16MHz */ + u8 CAPSELECT; /* 0: disable On-Chip pulling cap; 1: enable */ + u8 EN_RSSI; /* 0: disable RSSI; 1: enable RSSI */ + u8 Mod_Type; /* Modulation Type; */ + /* 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable */ + u8 TF_Type; /* Tracking Filter Type */ + /* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */ + + /* Calculated Settings */ + u32 RF_LO; /* Synth RF LO Frequency */ + u32 IF_LO; /* Synth IF LO Frequency */ + u32 TG_LO; /* Synth TG_LO Frequency */ + + /* Pointers to ControlName Arrays */ + u16 Init_Ctrl_Num; /* Number of INIT Control Names */ + TunerControl_struct + Init_Ctrl[INITCTRL_NUM]; /* INIT Control Names Array Pointer */ + + u16 CH_Ctrl_Num; /* Number of CH Control Names */ + TunerControl_struct + CH_Ctrl[CHCTRL_NUM]; /* CH Control Name Array Pointer */ + + u16 MXL_Ctrl_Num; /* Number of MXL Control Names */ + TunerControl_struct + MXL_Ctrl[MXLCTRL_NUM]; /* MXL Control Name Array Pointer */ + + /* Pointer to Tuner Register Array */ + u16 TunerRegs_Num; /* Number of Tuner Registers */ + TunerReg_struct + TunerRegs[TUNER_REGS_NUM]; /* Tuner Register Array Pointer */ +}; -error_status_get_tuner_i2c_device_addr: - return FUNCTION_ERROR; -} int mxl5005s_Initialize( struct dvb_usb_device* dib, @@ -310,24 +207,19 @@ error_status_set_tuner_registers: return FUNCTION_ERROR; } -int mxl5005s_GetRfFreqHz( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - unsigned long *pRfFreqHz - ) +// DONE +int mxl5005s_GetRfFreqHz(struct dvb_frontend *fe, unsigned long *pRfFreqHz) { - // Get tuner RF frequency in Hz from tuner module. - if(pTuner->IsRfFreqHzSet != YES) - goto error_status_get_tuner_rf_frequency; - - *pRfFreqHz = pTuner->RfFreqHz; - - - return FUNCTION_SUCCESS; + struct mxl5005s_state *state = fe->demodulator_priv; + int ret = -1; + /* Get tuner RF frequency in Hz from tuner module. */ + if(state->IsRfFreqHzSet == YES) { + *pRfFreqHz = state->RfFreqHz; + ret = 0; + } -error_status_get_tuner_rf_frequency: - return FUNCTION_ERROR; + return -1; } int mxl5005s_SetRegsWithTable( @@ -394,14 +286,13 @@ error_status_set_tuner_registers: return FUNCTION_ERROR; } -int mxl5005s_SetRegsWithTable( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, +int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, unsigned char *pAddrTable, unsigned char *pByteTable, int TableLen ) { + struct mxl5005s_state *state = fe->demodulator_priv; int i; u8 end_two_bytes_buf[]={ 0 , 0 }; u8 tuner_addr=0x00; @@ -423,31 +314,21 @@ int mxl5005s_SetRegsWithTable( return FUNCTION_SUCCESS; } -int mxl5005s_SetRegMaskBits( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, +int mxl5005s_SetRegMaskBits(struct dvb_frontend *fe, unsigned char RegAddr, unsigned char Msb, unsigned char Lsb, const unsigned char WritingValue ) { - MXL5005S_EXTRA_MODULE *pExtra; - + struct mxl5005s_state *state = fe->demodulator_priv; int i; unsigned char Mask; unsigned char Shift; - unsigned char RegByte; - - - // Get tuner extra module. - pExtra = (MXL5005S_EXTRA_MODULE *)pTuner->pExtra; - - - // Generate mask and shift according to MSB and LSB. + /* Generate mask and shift according to MSB and LSB. */ Mask = 0; for(i = Lsb; i < (unsigned char)(Msb + 1); i++) Mask |= 0x1 << i; @@ -455,20 +336,17 @@ int mxl5005s_SetRegMaskBits( Shift = Lsb; - // Get tuner register byte according to register adddress. + /* Get tuner register byte according to register adddress. */ MXL_RegRead(&pExtra->MxlDefinedTunerStructure, RegAddr, &RegByte); - - // Reserve register byte unmask bit with mask and inlay writing value into it. + /* Reserve register byte unmask bit with mask and inlay writing value into it. */ RegByte &= ~Mask; RegByte |= (WritingValue << Shift) & Mask; - - // Update tuner register byte table. + /* Update tuner register byte table. */ MXL_RegWrite(&pExtra->MxlDefinedTunerStructure, RegAddr, RegByte); - - // Write tuner register byte with writing byte. + /* Write tuner register byte with writing byte. */ if(pExtra->SetRegsWithTable( dib, pTuner, &RegAddr, &RegByte, LEN_1_BYTE) != FUNCTION_SUCCESS) goto error_status_set_tuner_registers; @@ -480,1350 +358,1321 @@ error_status_set_tuner_registers: return FUNCTION_ERROR; } -int mxl5005s_SetSpectrumMode( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - int SpectrumMode - ) +// DONE +int mxl5005s_SetSpectrumMode(struct dvb_frontend *fe, int SpectrumMode) { + struct mxl5005s_state *state = fe->demodulator_priv; static const unsigned char BbIqswapTable[SPECTRUM_MODE_NUM] = { - // BB_IQSWAP - 0, // Normal spectrum - 1, // Inverse spectrum + /* BB_IQSWAP */ + 0, /* Normal spectrum */ + 1, /* Inverse spectrum */ }; - - MXL5005S_EXTRA_MODULE *pExtra; - - - - // Get tuner extra module. - pExtra = (MXL5005S_EXTRA_MODULE *)pTuner->pExtra; - - - // Set BB_IQSWAP according to BB_IQSWAP table and spectrum mode. - if(pExtra->SetRegMaskBits(dib,pTuner, MXL5005S_BB_IQSWAP_ADDR, MXL5005S_BB_IQSWAP_MSB, - MXL5005S_BB_IQSWAP_LSB, BbIqswapTable[SpectrumMode]) != FUNCTION_SUCCESS) - goto error_status_set_tuner_registers; - + /* Set BB_IQSWAP according to BB_IQSWAP table and spectrum mode. */ + mxl5005s_SetRegMaskBits(fe, + MXL5005S_BB_IQSWAP_ADDR, + MXL5005S_BB_IQSWAP_MSB, + MXL5005S_BB_IQSWAP_LSB, + BbIqswapTable[SpectrumMode]); return FUNCTION_SUCCESS; - - -error_status_set_tuner_registers: - return FUNCTION_ERROR; } -int mxl5005s_SetBandwidthHz( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - unsigned long BandwidthHz - ) +// DONE +int mxl5005s_SetBandwidthHz(struct dvb_frontend *fe, unsigned long BandwidthHz) { - MXL5005S_EXTRA_MODULE *pExtra; + struct mxl5005s_state *state = fe->demodulator_priv; unsigned char BbDlpfBandsel; - - - // Get tuner extra module. - pExtra = (MXL5005S_EXTRA_MODULE *)pTuner->pExtra; - - - // Set BB_DLPF_BANDSEL according to bandwidth. + /* Set BB_DLPF_BANDSEL according to bandwidth. */ switch(BandwidthHz) { default: - case MXL5005S_BANDWIDTH_6MHZ: BbDlpfBandsel = 3; break; - case MXL5005S_BANDWIDTH_7MHZ: BbDlpfBandsel = 2; break; - case MXL5005S_BANDWIDTH_8MHZ: BbDlpfBandsel = 0; break; + case MXL5005S_BANDWIDTH_6MHZ: + BbDlpfBandsel = 3; + break; + case MXL5005S_BANDWIDTH_7MHZ: + BbDlpfBandsel = 2; + break; + case MXL5005S_BANDWIDTH_8MHZ: + BbDlpfBandsel = 0; + break; } if(pExtra->SetRegMaskBits(dib,pTuner, MXL5005S_BB_DLPF_BANDSEL_ADDR, MXL5005S_BB_DLPF_BANDSEL_MSB, - MXL5005S_BB_DLPF_BANDSEL_LSB, BbDlpfBandsel) != FUNCTION_SUCCESS) + MXL5005S_BB_DLPF_BANDSEL_LSB, BbDlpfBandsel) != 0) goto error_status_set_tuner_registers; - return FUNCTION_SUCCESS; + return 0; error_status_set_tuner_registers: - return FUNCTION_ERROR; -} - -void mxl5005s_SetI2cBridgeModuleTunerArg(TUNER_MODULE *pTuner) -{ - I2C_BRIDGE_MODULE *pI2cBridge; - - - - // Get I2C bridge module. - pI2cBridge = pTuner->pI2cBridge; - - // Set I2C bridge module tuner arguments. - pI2cBridge->pTunerDeviceAddr = &pTuner->DeviceAddr; - - - return; + return -1; } // The following context is source code provided by MaxLinear. // MaxLinear source code - MXL5005_Initialize.cpp -u16 MXL5005_RegisterInit(Tuner_struct *Tuner) +// DONE +u16 MXL5005_RegisterInit(struct dvb_frontend *fe) { - Tuner->TunerRegs_Num = TUNER_REGS_NUM ; -// Tuner->TunerRegs = (TunerReg_struct *) calloc( TUNER_REGS_NUM, sizeof(TunerReg_struct) ) ; + struct mxl5005s_state *state = fe->demodulator_priv; + state->TunerRegs_Num = TUNER_REGS_NUM ; +// state->TunerRegs = (TunerReg_struct *) calloc( TUNER_REGS_NUM, sizeof(TunerReg_struct) ) ; - Tuner->TunerRegs[0].Reg_Num = 9 ; - Tuner->TunerRegs[0].Reg_Val = 0x40 ; + state->TunerRegs[0].Reg_Num = 9 ; + state->TunerRegs[0].Reg_Val = 0x40 ; - Tuner->TunerRegs[1].Reg_Num = 11 ; - Tuner->TunerRegs[1].Reg_Val = 0x19 ; + state->TunerRegs[1].Reg_Num = 11 ; + state->TunerRegs[1].Reg_Val = 0x19 ; - Tuner->TunerRegs[2].Reg_Num = 12 ; - Tuner->TunerRegs[2].Reg_Val = 0x60 ; + state->TunerRegs[2].Reg_Num = 12 ; + state->TunerRegs[2].Reg_Val = 0x60 ; - Tuner->TunerRegs[3].Reg_Num = 13 ; - Tuner->TunerRegs[3].Reg_Val = 0x00 ; + state->TunerRegs[3].Reg_Num = 13 ; + state->TunerRegs[3].Reg_Val = 0x00 ; - Tuner->TunerRegs[4].Reg_Num = 14 ; - Tuner->TunerRegs[4].Reg_Val = 0x00 ; + state->TunerRegs[4].Reg_Num = 14 ; + state->TunerRegs[4].Reg_Val = 0x00 ; - Tuner->TunerRegs[5].Reg_Num = 15 ; - Tuner->TunerRegs[5].Reg_Val = 0xC0 ; + state->TunerRegs[5].Reg_Num = 15 ; + state->TunerRegs[5].Reg_Val = 0xC0 ; - Tuner->TunerRegs[6].Reg_Num = 16 ; - Tuner->TunerRegs[6].Reg_Val = 0x00 ; + state->TunerRegs[6].Reg_Num = 16 ; + state->TunerRegs[6].Reg_Val = 0x00 ; - Tuner->TunerRegs[7].Reg_Num = 17 ; - Tuner->TunerRegs[7].Reg_Val = 0x00 ; + state->TunerRegs[7].Reg_Num = 17 ; + state->TunerRegs[7].Reg_Val = 0x00 ; - Tuner->TunerRegs[8].Reg_Num = 18 ; - Tuner->TunerRegs[8].Reg_Val = 0x00 ; + state->TunerRegs[8].Reg_Num = 18 ; + state->TunerRegs[8].Reg_Val = 0x00 ; - Tuner->TunerRegs[9].Reg_Num = 19 ; - Tuner->TunerRegs[9].Reg_Val = 0x34 ; + state->TunerRegs[9].Reg_Num = 19 ; + state->TunerRegs[9].Reg_Val = 0x34 ; - Tuner->TunerRegs[10].Reg_Num = 21 ; - Tuner->TunerRegs[10].Reg_Val = 0x00 ; + state->TunerRegs[10].Reg_Num = 21 ; + state->TunerRegs[10].Reg_Val = 0x00 ; - Tuner->TunerRegs[11].Reg_Num = 22 ; - Tuner->TunerRegs[11].Reg_Val = 0x6B ; + state->TunerRegs[11].Reg_Num = 22 ; + state->TunerRegs[11].Reg_Val = 0x6B ; - Tuner->TunerRegs[12].Reg_Num = 23 ; - Tuner->TunerRegs[12].Reg_Val = 0x35 ; + state->TunerRegs[12].Reg_Num = 23 ; + state->TunerRegs[12].Reg_Val = 0x35 ; - Tuner->TunerRegs[13].Reg_Num = 24 ; - Tuner->TunerRegs[13].Reg_Val = 0x70 ; + state->TunerRegs[13].Reg_Num = 24 ; + state->TunerRegs[13].Reg_Val = 0x70 ; - Tuner->TunerRegs[14].Reg_Num = 25 ; - Tuner->TunerRegs[14].Reg_Val = 0x3E ; + state->TunerRegs[14].Reg_Num = 25 ; + state->TunerRegs[14].Reg_Val = 0x3E ; - Tuner->TunerRegs[15].Reg_Num = 26 ; - Tuner->TunerRegs[15].Reg_Val = 0x82 ; + state->TunerRegs[15].Reg_Num = 26 ; + state->TunerRegs[15].Reg_Val = 0x82 ; - Tuner->TunerRegs[16].Reg_Num = 31 ; - Tuner->TunerRegs[16].Reg_Val = 0x00 ; + state->TunerRegs[16].Reg_Num = 31 ; + state->TunerRegs[16].Reg_Val = 0x00 ; - Tuner->TunerRegs[17].Reg_Num = 32 ; - Tuner->TunerRegs[17].Reg_Val = 0x40 ; + state->TunerRegs[17].Reg_Num = 32 ; + state->TunerRegs[17].Reg_Val = 0x40 ; - Tuner->TunerRegs[18].Reg_Num = 33 ; - Tuner->TunerRegs[18].Reg_Val = 0x53 ; + state->TunerRegs[18].Reg_Num = 33 ; + state->TunerRegs[18].Reg_Val = 0x53 ; - Tuner->TunerRegs[19].Reg_Num = 34 ; - Tuner->TunerRegs[19].Reg_Val = 0x81 ; + state->TunerRegs[19].Reg_Num = 34 ; + state->TunerRegs[19].Reg_Val = 0x81 ; - Tuner->TunerRegs[20].Reg_Num = 35 ; - Tuner->TunerRegs[20].Reg_Val = 0xC9 ; + state->TunerRegs[20].Reg_Num = 35 ; + state->TunerRegs[20].Reg_Val = 0xC9 ; - Tuner->TunerRegs[21].Reg_Num = 36 ; - Tuner->TunerRegs[21].Reg_Val = 0x01 ; + state->TunerRegs[21].Reg_Num = 36 ; + state->TunerRegs[21].Reg_Val = 0x01 ; - Tuner->TunerRegs[22].Reg_Num = 37 ; - Tuner->TunerRegs[22].Reg_Val = 0x00 ; + state->TunerRegs[22].Reg_Num = 37 ; + state->TunerRegs[22].Reg_Val = 0x00 ; - Tuner->TunerRegs[23].Reg_Num = 41 ; - Tuner->TunerRegs[23].Reg_Val = 0x00 ; + state->TunerRegs[23].Reg_Num = 41 ; + state->TunerRegs[23].Reg_Val = 0x00 ; - Tuner->TunerRegs[24].Reg_Num = 42 ; - Tuner->TunerRegs[24].Reg_Val = 0xF8 ; + state->TunerRegs[24].Reg_Num = 42 ; + state->TunerRegs[24].Reg_Val = 0xF8 ; - Tuner->TunerRegs[25].Reg_Num = 43 ; - Tuner->TunerRegs[25].Reg_Val = 0x43 ; + state->TunerRegs[25].Reg_Num = 43 ; + state->TunerRegs[25].Reg_Val = 0x43 ; - Tuner->TunerRegs[26].Reg_Num = 44 ; - Tuner->TunerRegs[26].Reg_Val = 0x20 ; + state->TunerRegs[26].Reg_Num = 44 ; + state->TunerRegs[26].Reg_Val = 0x20 ; - Tuner->TunerRegs[27].Reg_Num = 45 ; - Tuner->TunerRegs[27].Reg_Val = 0x80 ; + state->TunerRegs[27].Reg_Num = 45 ; + state->TunerRegs[27].Reg_Val = 0x80 ; - Tuner->TunerRegs[28].Reg_Num = 46 ; - Tuner->TunerRegs[28].Reg_Val = 0x88 ; + state->TunerRegs[28].Reg_Num = 46 ; + state->TunerRegs[28].Reg_Val = 0x88 ; - Tuner->TunerRegs[29].Reg_Num = 47 ; - Tuner->TunerRegs[29].Reg_Val = 0x86 ; + state->TunerRegs[29].Reg_Num = 47 ; + state->TunerRegs[29].Reg_Val = 0x86 ; - Tuner->TunerRegs[30].Reg_Num = 48 ; - Tuner->TunerRegs[30].Reg_Val = 0x00 ; + state->TunerRegs[30].Reg_Num = 48 ; + state->TunerRegs[30].Reg_Val = 0x00 ; - Tuner->TunerRegs[31].Reg_Num = 49 ; - Tuner->TunerRegs[31].Reg_Val = 0x00 ; + state->TunerRegs[31].Reg_Num = 49 ; + state->TunerRegs[31].Reg_Val = 0x00 ; - Tuner->TunerRegs[32].Reg_Num = 53 ; - Tuner->TunerRegs[32].Reg_Val = 0x94 ; + state->TunerRegs[32].Reg_Num = 53 ; + state->TunerRegs[32].Reg_Val = 0x94 ; - Tuner->TunerRegs[33].Reg_Num = 54 ; - Tuner->TunerRegs[33].Reg_Val = 0xFA ; + state->TunerRegs[33].Reg_Num = 54 ; + state->TunerRegs[33].Reg_Val = 0xFA ; - Tuner->TunerRegs[34].Reg_Num = 55 ; - Tuner->TunerRegs[34].Reg_Val = 0x92 ; + state->TunerRegs[34].Reg_Num = 55 ; + state->TunerRegs[34].Reg_Val = 0x92 ; - Tuner->TunerRegs[35].Reg_Num = 56 ; - Tuner->TunerRegs[35].Reg_Val = 0x80 ; + state->TunerRegs[35].Reg_Num = 56 ; + state->TunerRegs[35].Reg_Val = 0x80 ; - Tuner->TunerRegs[36].Reg_Num = 57 ; - Tuner->TunerRegs[36].Reg_Val = 0x41 ; + state->TunerRegs[36].Reg_Num = 57 ; + state->TunerRegs[36].Reg_Val = 0x41 ; - Tuner->TunerRegs[37].Reg_Num = 58 ; - Tuner->TunerRegs[37].Reg_Val = 0xDB ; + state->TunerRegs[37].Reg_Num = 58 ; + state->TunerRegs[37].Reg_Val = 0xDB ; - Tuner->TunerRegs[38].Reg_Num = 59 ; - Tuner->TunerRegs[38].Reg_Val = 0x00 ; + state->TunerRegs[38].Reg_Num = 59 ; + state->TunerRegs[38].Reg_Val = 0x00 ; - Tuner->TunerRegs[39].Reg_Num = 60 ; - Tuner->TunerRegs[39].Reg_Val = 0x00 ; + state->TunerRegs[39].Reg_Num = 60 ; + state->TunerRegs[39].Reg_Val = 0x00 ; - Tuner->TunerRegs[40].Reg_Num = 61 ; - Tuner->TunerRegs[40].Reg_Val = 0x00 ; + state->TunerRegs[40].Reg_Num = 61 ; + state->TunerRegs[40].Reg_Val = 0x00 ; - Tuner->TunerRegs[41].Reg_Num = 62 ; - Tuner->TunerRegs[41].Reg_Val = 0x00 ; + state->TunerRegs[41].Reg_Num = 62 ; + state->TunerRegs[41].Reg_Val = 0x00 ; - Tuner->TunerRegs[42].Reg_Num = 65 ; - Tuner->TunerRegs[42].Reg_Val = 0xF8 ; + state->TunerRegs[42].Reg_Num = 65 ; + state->TunerRegs[42].Reg_Val = 0xF8 ; - Tuner->TunerRegs[43].Reg_Num = 66 ; - Tuner->TunerRegs[43].Reg_Val = 0xE4 ; + state->TunerRegs[43].Reg_Num = 66 ; + state->TunerRegs[43].Reg_Val = 0xE4 ; - Tuner->TunerRegs[44].Reg_Num = 67 ; - Tuner->TunerRegs[44].Reg_Val = 0x90 ; + state->TunerRegs[44].Reg_Num = 67 ; + state->TunerRegs[44].Reg_Val = 0x90 ; - Tuner->TunerRegs[45].Reg_Num = 68 ; - Tuner->TunerRegs[45].Reg_Val = 0xC0 ; + state->TunerRegs[45].Reg_Num = 68 ; + state->TunerRegs[45].Reg_Val = 0xC0 ; - Tuner->TunerRegs[46].Reg_Num = 69 ; - Tuner->TunerRegs[46].Reg_Val = 0x01 ; + state->TunerRegs[46].Reg_Num = 69 ; + state->TunerRegs[46].Reg_Val = 0x01 ; - Tuner->TunerRegs[47].Reg_Num = 70 ; - Tuner->TunerRegs[47].Reg_Val = 0x50 ; + state->TunerRegs[47].Reg_Num = 70 ; + state->TunerRegs[47].Reg_Val = 0x50 ; - Tuner->TunerRegs[48].Reg_Num = 71 ; - Tuner->TunerRegs[48].Reg_Val = 0x06 ; + state->TunerRegs[48].Reg_Num = 71 ; + state->TunerRegs[48].Reg_Val = 0x06 ; - Tuner->TunerRegs[49].Reg_Num = 72 ; - Tuner->TunerRegs[49].Reg_Val = 0x00 ; + state->TunerRegs[49].Reg_Num = 72 ; + state->TunerRegs[49].Reg_Val = 0x00 ; - Tuner->TunerRegs[50].Reg_Num = 73 ; - Tuner->TunerRegs[50].Reg_Val = 0x20 ; + state->TunerRegs[50].Reg_Num = 73 ; + state->TunerRegs[50].Reg_Val = 0x20 ; - Tuner->TunerRegs[51].Reg_Num = 76 ; - Tuner->TunerRegs[51].Reg_Val = 0xBB ; + state->TunerRegs[51].Reg_Num = 76 ; + state->TunerRegs[51].Reg_Val = 0xBB ; - Tuner->TunerRegs[52].Reg_Num = 77 ; - Tuner->TunerRegs[52].Reg_Val = 0x13 ; + state->TunerRegs[52].Reg_Num = 77 ; + state->TunerRegs[52].Reg_Val = 0x13 ; - Tuner->TunerRegs[53].Reg_Num = 81 ; - Tuner->TunerRegs[53].Reg_Val = 0x04 ; + state->TunerRegs[53].Reg_Num = 81 ; + state->TunerRegs[53].Reg_Val = 0x04 ; - Tuner->TunerRegs[54].Reg_Num = 82 ; - Tuner->TunerRegs[54].Reg_Val = 0x75 ; + state->TunerRegs[54].Reg_Num = 82 ; + state->TunerRegs[54].Reg_Val = 0x75 ; - Tuner->TunerRegs[55].Reg_Num = 83 ; - Tuner->TunerRegs[55].Reg_Val = 0x00 ; + state->TunerRegs[55].Reg_Num = 83 ; + state->TunerRegs[55].Reg_Val = 0x00 ; - Tuner->TunerRegs[56].Reg_Num = 84 ; - Tuner->TunerRegs[56].Reg_Val = 0x00 ; + state->TunerRegs[56].Reg_Num = 84 ; + state->TunerRegs[56].Reg_Val = 0x00 ; - Tuner->TunerRegs[57].Reg_Num = 85 ; - Tuner->TunerRegs[57].Reg_Val = 0x00 ; + state->TunerRegs[57].Reg_Num = 85 ; + state->TunerRegs[57].Reg_Val = 0x00 ; - Tuner->TunerRegs[58].Reg_Num = 91 ; - Tuner->TunerRegs[58].Reg_Val = 0x70 ; + state->TunerRegs[58].Reg_Num = 91 ; + state->TunerRegs[58].Reg_Val = 0x70 ; - Tuner->TunerRegs[59].Reg_Num = 92 ; - Tuner->TunerRegs[59].Reg_Val = 0x00 ; + state->TunerRegs[59].Reg_Num = 92 ; + state->TunerRegs[59].Reg_Val = 0x00 ; - Tuner->TunerRegs[60].Reg_Num = 93 ; - Tuner->TunerRegs[60].Reg_Val = 0x00 ; + state->TunerRegs[60].Reg_Num = 93 ; + state->TunerRegs[60].Reg_Val = 0x00 ; - Tuner->TunerRegs[61].Reg_Num = 94 ; - Tuner->TunerRegs[61].Reg_Val = 0x00 ; + state->TunerRegs[61].Reg_Num = 94 ; + state->TunerRegs[61].Reg_Val = 0x00 ; - Tuner->TunerRegs[62].Reg_Num = 95 ; - Tuner->TunerRegs[62].Reg_Val = 0x0C ; + state->TunerRegs[62].Reg_Num = 95 ; + state->TunerRegs[62].Reg_Val = 0x0C ; - Tuner->TunerRegs[63].Reg_Num = 96 ; - Tuner->TunerRegs[63].Reg_Val = 0x00 ; + state->TunerRegs[63].Reg_Num = 96 ; + state->TunerRegs[63].Reg_Val = 0x00 ; - Tuner->TunerRegs[64].Reg_Num = 97 ; - Tuner->TunerRegs[64].Reg_Val = 0x00 ; + state->TunerRegs[64].Reg_Num = 97 ; + state->TunerRegs[64].Reg_Val = 0x00 ; - Tuner->TunerRegs[65].Reg_Num = 98 ; - Tuner->TunerRegs[65].Reg_Val = 0xE2 ; + state->TunerRegs[65].Reg_Num = 98 ; + state->TunerRegs[65].Reg_Val = 0xE2 ; - Tuner->TunerRegs[66].Reg_Num = 99 ; - Tuner->TunerRegs[66].Reg_Val = 0x00 ; + state->TunerRegs[66].Reg_Num = 99 ; + state->TunerRegs[66].Reg_Val = 0x00 ; - Tuner->TunerRegs[67].Reg_Num = 100 ; - Tuner->TunerRegs[67].Reg_Val = 0x00 ; + state->TunerRegs[67].Reg_Num = 100 ; + state->TunerRegs[67].Reg_Val = 0x00 ; - Tuner->TunerRegs[68].Reg_Num = 101 ; - Tuner->TunerRegs[68].Reg_Val = 0x12 ; + state->TunerRegs[68].Reg_Num = 101 ; + state->TunerRegs[68].Reg_Val = 0x12 ; - Tuner->TunerRegs[69].Reg_Num = 102 ; - Tuner->TunerRegs[69].Reg_Val = 0x80 ; + state->TunerRegs[69].Reg_Num = 102 ; + state->TunerRegs[69].Reg_Val = 0x80 ; - Tuner->TunerRegs[70].Reg_Num = 103 ; - Tuner->TunerRegs[70].Reg_Val = 0x32 ; + state->TunerRegs[70].Reg_Num = 103 ; + state->TunerRegs[70].Reg_Val = 0x32 ; - Tuner->TunerRegs[71].Reg_Num = 104 ; - Tuner->TunerRegs[71].Reg_Val = 0xB4 ; + state->TunerRegs[71].Reg_Num = 104 ; + state->TunerRegs[71].Reg_Val = 0xB4 ; - Tuner->TunerRegs[72].Reg_Num = 105 ; - Tuner->TunerRegs[72].Reg_Val = 0x60 ; + state->TunerRegs[72].Reg_Num = 105 ; + state->TunerRegs[72].Reg_Val = 0x60 ; - Tuner->TunerRegs[73].Reg_Num = 106 ; - Tuner->TunerRegs[73].Reg_Val = 0x83 ; + state->TunerRegs[73].Reg_Num = 106 ; + state->TunerRegs[73].Reg_Val = 0x83 ; - Tuner->TunerRegs[74].Reg_Num = 107 ; - Tuner->TunerRegs[74].Reg_Val = 0x84 ; + state->TunerRegs[74].Reg_Num = 107 ; + state->TunerRegs[74].Reg_Val = 0x84 ; - Tuner->TunerRegs[75].Reg_Num = 108 ; - Tuner->TunerRegs[75].Reg_Val = 0x9C ; + state->TunerRegs[75].Reg_Num = 108 ; + state->TunerRegs[75].Reg_Val = 0x9C ; - Tuner->TunerRegs[76].Reg_Num = 109 ; - Tuner->TunerRegs[76].Reg_Val = 0x02 ; + state->TunerRegs[76].Reg_Num = 109 ; + state->TunerRegs[76].Reg_Val = 0x02 ; - Tuner->TunerRegs[77].Reg_Num = 110 ; - Tuner->TunerRegs[77].Reg_Val = 0x81 ; + state->TunerRegs[77].Reg_Num = 110 ; + state->TunerRegs[77].Reg_Val = 0x81 ; - Tuner->TunerRegs[78].Reg_Num = 111 ; - Tuner->TunerRegs[78].Reg_Val = 0xC0 ; + state->TunerRegs[78].Reg_Num = 111 ; + state->TunerRegs[78].Reg_Val = 0xC0 ; - Tuner->TunerRegs[79].Reg_Num = 112 ; - Tuner->TunerRegs[79].Reg_Val = 0x10 ; + state->TunerRegs[79].Reg_Num = 112 ; + state->TunerRegs[79].Reg_Val = 0x10 ; - Tuner->TunerRegs[80].Reg_Num = 131 ; - Tuner->TunerRegs[80].Reg_Val = 0x8A ; + state->TunerRegs[80].Reg_Num = 131 ; + state->TunerRegs[80].Reg_Val = 0x8A ; - Tuner->TunerRegs[81].Reg_Num = 132 ; - Tuner->TunerRegs[81].Reg_Val = 0x10 ; + state->TunerRegs[81].Reg_Num = 132 ; + state->TunerRegs[81].Reg_Val = 0x10 ; - Tuner->TunerRegs[82].Reg_Num = 133 ; - Tuner->TunerRegs[82].Reg_Val = 0x24 ; + state->TunerRegs[82].Reg_Num = 133 ; + state->TunerRegs[82].Reg_Val = 0x24 ; - Tuner->TunerRegs[83].Reg_Num = 134 ; - Tuner->TunerRegs[83].Reg_Val = 0x00 ; + state->TunerRegs[83].Reg_Num = 134 ; + state->TunerRegs[83].Reg_Val = 0x00 ; - Tuner->TunerRegs[84].Reg_Num = 135 ; - Tuner->TunerRegs[84].Reg_Val = 0x00 ; + state->TunerRegs[84].Reg_Num = 135 ; + state->TunerRegs[84].Reg_Val = 0x00 ; - Tuner->TunerRegs[85].Reg_Num = 136 ; - Tuner->TunerRegs[85].Reg_Val = 0x7E ; + state->TunerRegs[85].Reg_Num = 136 ; + state->TunerRegs[85].Reg_Val = 0x7E ; - Tuner->TunerRegs[86].Reg_Num = 137 ; - Tuner->TunerRegs[86].Reg_Val = 0x40 ; + state->TunerRegs[86].Reg_Num = 137 ; + state->TunerRegs[86].Reg_Val = 0x40 ; - Tuner->TunerRegs[87].Reg_Num = 138 ; - Tuner->TunerRegs[87].Reg_Val = 0x38 ; + state->TunerRegs[87].Reg_Num = 138 ; + state->TunerRegs[87].Reg_Val = 0x38 ; - Tuner->TunerRegs[88].Reg_Num = 146 ; - Tuner->TunerRegs[88].Reg_Val = 0xF6 ; + state->TunerRegs[88].Reg_Num = 146 ; + state->TunerRegs[88].Reg_Val = 0xF6 ; - Tuner->TunerRegs[89].Reg_Num = 147 ; - Tuner->TunerRegs[89].Reg_Val = 0x1A ; + state->TunerRegs[89].Reg_Num = 147 ; + state->TunerRegs[89].Reg_Val = 0x1A ; - Tuner->TunerRegs[90].Reg_Num = 148 ; - Tuner->TunerRegs[90].Reg_Val = 0x62 ; + state->TunerRegs[90].Reg_Num = 148 ; + state->TunerRegs[90].Reg_Val = 0x62 ; - Tuner->TunerRegs[91].Reg_Num = 149 ; - Tuner->TunerRegs[91].Reg_Val = 0x33 ; + state->TunerRegs[91].Reg_Num = 149 ; + state->TunerRegs[91].Reg_Val = 0x33 ; - Tuner->TunerRegs[92].Reg_Num = 150 ; - Tuner->TunerRegs[92].Reg_Val = 0x80 ; + state->TunerRegs[92].Reg_Num = 150 ; + state->TunerRegs[92].Reg_Val = 0x80 ; - Tuner->TunerRegs[93].Reg_Num = 156 ; - Tuner->TunerRegs[93].Reg_Val = 0x56 ; + state->TunerRegs[93].Reg_Num = 156 ; + state->TunerRegs[93].Reg_Val = 0x56 ; - Tuner->TunerRegs[94].Reg_Num = 157 ; - Tuner->TunerRegs[94].Reg_Val = 0x17 ; + state->TunerRegs[94].Reg_Num = 157 ; + state->TunerRegs[94].Reg_Val = 0x17 ; - Tuner->TunerRegs[95].Reg_Num = 158 ; - Tuner->TunerRegs[95].Reg_Val = 0xA9 ; + state->TunerRegs[95].Reg_Num = 158 ; + state->TunerRegs[95].Reg_Val = 0xA9 ; - Tuner->TunerRegs[96].Reg_Num = 159 ; - Tuner->TunerRegs[96].Reg_Val = 0x00 ; + state->TunerRegs[96].Reg_Num = 159 ; + state->TunerRegs[96].Reg_Val = 0x00 ; - Tuner->TunerRegs[97].Reg_Num = 160 ; - Tuner->TunerRegs[97].Reg_Val = 0x00 ; + state->TunerRegs[97].Reg_Num = 160 ; + state->TunerRegs[97].Reg_Val = 0x00 ; - Tuner->TunerRegs[98].Reg_Num = 161 ; - Tuner->TunerRegs[98].Reg_Val = 0x00 ; + state->TunerRegs[98].Reg_Num = 161 ; + state->TunerRegs[98].Reg_Val = 0x00 ; - Tuner->TunerRegs[99].Reg_Num = 162 ; - Tuner->TunerRegs[99].Reg_Val = 0x40 ; + state->TunerRegs[99].Reg_Num = 162 ; + state->TunerRegs[99].Reg_Val = 0x40 ; - Tuner->TunerRegs[100].Reg_Num = 166 ; - Tuner->TunerRegs[100].Reg_Val = 0xAE ; + state->TunerRegs[100].Reg_Num = 166 ; + state->TunerRegs[100].Reg_Val = 0xAE ; - Tuner->TunerRegs[101].Reg_Num = 167 ; - Tuner->TunerRegs[101].Reg_Val = 0x1B ; + state->TunerRegs[101].Reg_Num = 167 ; + state->TunerRegs[101].Reg_Val = 0x1B ; - Tuner->TunerRegs[102].Reg_Num = 168 ; - Tuner->TunerRegs[102].Reg_Val = 0xF2 ; + state->TunerRegs[102].Reg_Num = 168 ; + state->TunerRegs[102].Reg_Val = 0xF2 ; - Tuner->TunerRegs[103].Reg_Num = 195 ; - Tuner->TunerRegs[103].Reg_Val = 0x00 ; + state->TunerRegs[103].Reg_Num = 195 ; + state->TunerRegs[103].Reg_Val = 0x00 ; return 0 ; } -u16 MXL5005_ControlInit(Tuner_struct *Tuner) +// DONE +u16 MXL5005_ControlInit(struct dvb_frontend *fe) { - Tuner->Init_Ctrl_Num = INITCTRL_NUM ; - - Tuner->Init_Ctrl[0].Ctrl_Num = DN_IQTN_AMP_CUT ; - Tuner->Init_Ctrl[0].size = 1 ; - Tuner->Init_Ctrl[0].addr[0] = 73; - Tuner->Init_Ctrl[0].bit[0] = 7; - Tuner->Init_Ctrl[0].val[0] = 0; - - Tuner->Init_Ctrl[1].Ctrl_Num = BB_MODE ; - Tuner->Init_Ctrl[1].size = 1 ; - Tuner->Init_Ctrl[1].addr[0] = 53; - Tuner->Init_Ctrl[1].bit[0] = 2; - Tuner->Init_Ctrl[1].val[0] = 1; - - Tuner->Init_Ctrl[2].Ctrl_Num = BB_BUF ; - Tuner->Init_Ctrl[2].size = 2 ; - Tuner->Init_Ctrl[2].addr[0] = 53; - Tuner->Init_Ctrl[2].bit[0] = 1; - Tuner->Init_Ctrl[2].val[0] = 0; - Tuner->Init_Ctrl[2].addr[1] = 57; - Tuner->Init_Ctrl[2].bit[1] = 0; - Tuner->Init_Ctrl[2].val[1] = 1; - - Tuner->Init_Ctrl[3].Ctrl_Num = BB_BUF_OA ; - Tuner->Init_Ctrl[3].size = 1 ; - Tuner->Init_Ctrl[3].addr[0] = 53; - Tuner->Init_Ctrl[3].bit[0] = 0; - Tuner->Init_Ctrl[3].val[0] = 0; - - Tuner->Init_Ctrl[4].Ctrl_Num = BB_ALPF_BANDSELECT ; - Tuner->Init_Ctrl[4].size = 3 ; - Tuner->Init_Ctrl[4].addr[0] = 53; - Tuner->Init_Ctrl[4].bit[0] = 5; - Tuner->Init_Ctrl[4].val[0] = 0; - Tuner->Init_Ctrl[4].addr[1] = 53; - Tuner->Init_Ctrl[4].bit[1] = 6; - Tuner->Init_Ctrl[4].val[1] = 0; - Tuner->Init_Ctrl[4].addr[2] = 53; - Tuner->Init_Ctrl[4].bit[2] = 7; - Tuner->Init_Ctrl[4].val[2] = 1; - - Tuner->Init_Ctrl[5].Ctrl_Num = BB_IQSWAP ; - Tuner->Init_Ctrl[5].size = 1 ; - Tuner->Init_Ctrl[5].addr[0] = 59; - Tuner->Init_Ctrl[5].bit[0] = 0; - Tuner->Init_Ctrl[5].val[0] = 0; - - Tuner->Init_Ctrl[6].Ctrl_Num = BB_DLPF_BANDSEL ; - Tuner->Init_Ctrl[6].size = 2 ; - Tuner->Init_Ctrl[6].addr[0] = 53; - Tuner->Init_Ctrl[6].bit[0] = 3; - Tuner->Init_Ctrl[6].val[0] = 0; - Tuner->Init_Ctrl[6].addr[1] = 53; - Tuner->Init_Ctrl[6].bit[1] = 4; - Tuner->Init_Ctrl[6].val[1] = 1; - - Tuner->Init_Ctrl[7].Ctrl_Num = RFSYN_CHP_GAIN ; - Tuner->Init_Ctrl[7].size = 4 ; - Tuner->Init_Ctrl[7].addr[0] = 22; - Tuner->Init_Ctrl[7].bit[0] = 4; - Tuner->Init_Ctrl[7].val[0] = 0; - Tuner->Init_Ctrl[7].addr[1] = 22; - Tuner->Init_Ctrl[7].bit[1] = 5; - Tuner->Init_Ctrl[7].val[1] = 1; - Tuner->Init_Ctrl[7].addr[2] = 22; - Tuner->Init_Ctrl[7].bit[2] = 6; - Tuner->Init_Ctrl[7].val[2] = 1; - Tuner->Init_Ctrl[7].addr[3] = 22; - Tuner->Init_Ctrl[7].bit[3] = 7; - Tuner->Init_Ctrl[7].val[3] = 0; - - Tuner->Init_Ctrl[8].Ctrl_Num = RFSYN_EN_CHP_HIGAIN ; - Tuner->Init_Ctrl[8].size = 1 ; - Tuner->Init_Ctrl[8].addr[0] = 22; - Tuner->Init_Ctrl[8].bit[0] = 2; - Tuner->Init_Ctrl[8].val[0] = 0; - - Tuner->Init_Ctrl[9].Ctrl_Num = AGC_IF ; - Tuner->Init_Ctrl[9].size = 4 ; - Tuner->Init_Ctrl[9].addr[0] = 76; - Tuner->Init_Ctrl[9].bit[0] = 0; - Tuner->Init_Ctrl[9].val[0] = 1; - Tuner->Init_Ctrl[9].addr[1] = 76; - Tuner->Init_Ctrl[9].bit[1] = 1; - Tuner->Init_Ctrl[9].val[1] = 1; - Tuner->Init_Ctrl[9].addr[2] = 76; - Tuner->Init_Ctrl[9].bit[2] = 2; - Tuner->Init_Ctrl[9].val[2] = 0; - Tuner->Init_Ctrl[9].addr[3] = 76; - Tuner->Init_Ctrl[9].bit[3] = 3; - Tuner->Init_Ctrl[9].val[3] = 1; - - Tuner->Init_Ctrl[10].Ctrl_Num = AGC_RF ; - Tuner->Init_Ctrl[10].size = 4 ; - Tuner->Init_Ctrl[10].addr[0] = 76; - Tuner->Init_Ctrl[10].bit[0] = 4; - Tuner->Init_Ctrl[10].val[0] = 1; - Tuner->Init_Ctrl[10].addr[1] = 76; - Tuner->Init_Ctrl[10].bit[1] = 5; - Tuner->Init_Ctrl[10].val[1] = 1; - Tuner->Init_Ctrl[10].addr[2] = 76; - Tuner->Init_Ctrl[10].bit[2] = 6; - Tuner->Init_Ctrl[10].val[2] = 0; - Tuner->Init_Ctrl[10].addr[3] = 76; - Tuner->Init_Ctrl[10].bit[3] = 7; - Tuner->Init_Ctrl[10].val[3] = 1; - - Tuner->Init_Ctrl[11].Ctrl_Num = IF_DIVVAL ; - Tuner->Init_Ctrl[11].size = 5 ; - Tuner->Init_Ctrl[11].addr[0] = 43; - Tuner->Init_Ctrl[11].bit[0] = 3; - Tuner->Init_Ctrl[11].val[0] = 0; - Tuner->Init_Ctrl[11].addr[1] = 43; - Tuner->Init_Ctrl[11].bit[1] = 4; - Tuner->Init_Ctrl[11].val[1] = 0; - Tuner->Init_Ctrl[11].addr[2] = 43; - Tuner->Init_Ctrl[11].bit[2] = 5; - Tuner->Init_Ctrl[11].val[2] = 0; - Tuner->Init_Ctrl[11].addr[3] = 43; - Tuner->Init_Ctrl[11].bit[3] = 6; - Tuner->Init_Ctrl[11].val[3] = 1; - Tuner->Init_Ctrl[11].addr[4] = 43; - Tuner->Init_Ctrl[11].bit[4] = 7; - Tuner->Init_Ctrl[11].val[4] = 0; - - Tuner->Init_Ctrl[12].Ctrl_Num = IF_VCO_BIAS ; - Tuner->Init_Ctrl[12].size = 6 ; - Tuner->Init_Ctrl[12].addr[0] = 44; - Tuner->Init_Ctrl[12].bit[0] = 2; - Tuner->Init_Ctrl[12].val[0] = 0; - Tuner->Init_Ctrl[12].addr[1] = 44; - Tuner->Init_Ctrl[12].bit[1] = 3; - Tuner->Init_Ctrl[12].val[1] = 0; - Tuner->Init_Ctrl[12].addr[2] = 44; - Tuner->Init_Ctrl[12].bit[2] = 4; - Tuner->Init_Ctrl[12].val[2] = 0; - Tuner->Init_Ctrl[12].addr[3] = 44; - Tuner->Init_Ctrl[12].bit[3] = 5; - Tuner->Init_Ctrl[12].val[3] = 1; - Tuner->Init_Ctrl[12].addr[4] = 44; - Tuner->Init_Ctrl[12].bit[4] = 6; - Tuner->Init_Ctrl[12].val[4] = 0; - Tuner->Init_Ctrl[12].addr[5] = 44; - Tuner->Init_Ctrl[12].bit[5] = 7; - Tuner->Init_Ctrl[12].val[5] = 0; - - Tuner->Init_Ctrl[13].Ctrl_Num = CHCAL_INT_MOD_IF ; - Tuner->Init_Ctrl[13].size = 7 ; - Tuner->Init_Ctrl[13].addr[0] = 11; - Tuner->Init_Ctrl[13].bit[0] = 0; - Tuner->Init_Ctrl[13].val[0] = 1; - Tuner->Init_Ctrl[13].addr[1] = 11; - Tuner->Init_Ctrl[13].bit[1] = 1; - Tuner->Init_Ctrl[13].val[1] = 0; - Tuner->Init_Ctrl[13].addr[2] = 11; - Tuner->Init_Ctrl[13].bit[2] = 2; - Tuner->Init_Ctrl[13].val[2] = 0; - Tuner->Init_Ctrl[13].addr[3] = 11; - Tuner->Init_Ctrl[13].bit[3] = 3; - Tuner->Init_Ctrl[13].val[3] = 1; - Tuner->Init_Ctrl[13].addr[4] = 11; - Tuner->Init_Ctrl[13].bit[4] = 4; - Tuner->Init_Ctrl[13].val[4] = 1; - Tuner->Init_Ctrl[13].addr[5] = 11; - Tuner->Init_Ctrl[13].bit[5] = 5; - Tuner->Init_Ctrl[13].val[5] = 0; - Tuner->Init_Ctrl[13].addr[6] = 11; - Tuner->Init_Ctrl[13].bit[6] = 6; - Tuner->Init_Ctrl[13].val[6] = 0; - - Tuner->Init_Ctrl[14].Ctrl_Num = CHCAL_FRAC_MOD_IF ; - Tuner->Init_Ctrl[14].size = 16 ; - Tuner->Init_Ctrl[14].addr[0] = 13; - Tuner->Init_Ctrl[14].bit[0] = 0; - Tuner->Init_Ctrl[14].val[0] = 0; - Tuner->Init_Ctrl[14].addr[1] = 13; - Tuner->Init_Ctrl[14].bit[1] = 1; - Tuner->Init_Ctrl[14].val[1] = 0; - Tuner->Init_Ctrl[14].addr[2] = 13; - Tuner->Init_Ctrl[14].bit[2] = 2; - Tuner->Init_Ctrl[14].val[2] = 0; - Tuner->Init_Ctrl[14].addr[3] = 13; - Tuner->Init_Ctrl[14].bit[3] = 3; - Tuner->Init_Ctrl[14].val[3] = 0; - Tuner->Init_Ctrl[14].addr[4] = 13; - Tuner->Init_Ctrl[14].bit[4] = 4; - Tuner->Init_Ctrl[14].val[4] = 0; - Tuner->Init_Ctrl[14].addr[5] = 13; - Tuner->Init_Ctrl[14].bit[5] = 5; - Tuner->Init_Ctrl[14].val[5] = 0; - Tuner->Init_Ctrl[14].addr[6] = 13; - Tuner->Init_Ctrl[14].bit[6] = 6; - Tuner->Init_Ctrl[14].val[6] = 0; - Tuner->Init_Ctrl[14].addr[7] = 13; - Tuner->Init_Ctrl[14].bit[7] = 7; - Tuner->Init_Ctrl[14].val[7] = 0; - Tuner->Init_Ctrl[14].addr[8] = 12; - Tuner->Init_Ctrl[14].bit[8] = 0; - Tuner->Init_Ctrl[14].val[8] = 0; - Tuner->Init_Ctrl[14].addr[9] = 12; - Tuner->Init_Ctrl[14].bit[9] = 1; - Tuner->Init_Ctrl[14].val[9] = 0; - Tuner->Init_Ctrl[14].addr[10] = 12; - Tuner->Init_Ctrl[14].bit[10] = 2; - Tuner->Init_Ctrl[14].val[10] = 0; - Tuner->Init_Ctrl[14].addr[11] = 12; - Tuner->Init_Ctrl[14].bit[11] = 3; - Tuner->Init_Ctrl[14].val[11] = 0; - Tuner->Init_Ctrl[14].addr[12] = 12; - Tuner->Init_Ctrl[14].bit[12] = 4; - Tuner->Init_Ctrl[14].val[12] = 0; - Tuner->Init_Ctrl[14].addr[13] = 12; - Tuner->Init_Ctrl[14].bit[13] = 5; - Tuner->Init_Ctrl[14].val[13] = 1; - Tuner->Init_Ctrl[14].addr[14] = 12; - Tuner->Init_Ctrl[14].bit[14] = 6; - Tuner->Init_Ctrl[14].val[14] = 1; - Tuner->Init_Ctrl[14].addr[15] = 12; - Tuner->Init_Ctrl[14].bit[15] = 7; - Tuner->Init_Ctrl[14].val[15] = 0; - - Tuner->Init_Ctrl[15].Ctrl_Num = DRV_RES_SEL ; - Tuner->Init_Ctrl[15].size = 3 ; - Tuner->Init_Ctrl[15].addr[0] = 147; - Tuner->Init_Ctrl[15].bit[0] = 2; - Tuner->Init_Ctrl[15].val[0] = 0; - Tuner->Init_Ctrl[15].addr[1] = 147; - Tuner->Init_Ctrl[15].bit[1] = 3; - Tuner->Init_Ctrl[15].val[1] = 1; - Tuner->Init_Ctrl[15].addr[2] = 147; - Tuner->Init_Ctrl[15].bit[2] = 4; - Tuner->Init_Ctrl[15].val[2] = 1; - - Tuner->Init_Ctrl[16].Ctrl_Num = I_DRIVER ; - Tuner->Init_Ctrl[16].size = 2 ; - Tuner->Init_Ctrl[16].addr[0] = 147; - Tuner->Init_Ctrl[16].bit[0] = 0; - Tuner->Init_Ctrl[16].val[0] = 0; - Tuner->Init_Ctrl[16].addr[1] = 147; - Tuner->Init_Ctrl[16].bit[1] = 1; - Tuner->Init_Ctrl[16].val[1] = 1; - - Tuner->Init_Ctrl[17].Ctrl_Num = EN_AAF ; - Tuner->Init_Ctrl[17].size = 1 ; - Tuner->Init_Ctrl[17].addr[0] = 147; - Tuner->Init_Ctrl[17].bit[0] = 7; - Tuner->Init_Ctrl[17].val[0] = 0; - - Tuner->Init_Ctrl[18].Ctrl_Num = EN_3P ; - Tuner->Init_Ctrl[18].size = 1 ; - Tuner->Init_Ctrl[18].addr[0] = 147; - Tuner->Init_Ctrl[18].bit[0] = 6; - Tuner->Init_Ctrl[18].val[0] = 0; - - Tuner->Init_Ctrl[19].Ctrl_Num = EN_AUX_3P ; - Tuner->Init_Ctrl[19].size = 1 ; - Tuner->Init_Ctrl[19].addr[0] = 156; - Tuner->Init_Ctrl[19].bit[0] = 0; - Tuner->Init_Ctrl[19].val[0] = 0; - - Tuner->Init_Ctrl[20].Ctrl_Num = SEL_AAF_BAND ; - Tuner->Init_Ctrl[20].size = 1 ; - Tuner->Init_Ctrl[20].addr[0] = 147; - Tuner->Init_Ctrl[20].bit[0] = 5; - Tuner->Init_Ctrl[20].val[0] = 0; - - Tuner->Init_Ctrl[21].Ctrl_Num = SEQ_ENCLK16_CLK_OUT ; - Tuner->Init_Ctrl[21].size = 1 ; - Tuner->Init_Ctrl[21].addr[0] = 137; - Tuner->Init_Ctrl[21].bit[0] = 4; - Tuner->Init_Ctrl[21].val[0] = 0; - - Tuner->Init_Ctrl[22].Ctrl_Num = SEQ_SEL4_16B ; - Tuner->Init_Ctrl[22].size = 1 ; - Tuner->Init_Ctrl[22].addr[0] = 137; - Tuner->Init_Ctrl[22].bit[0] = 7; - Tuner->Init_Ctrl[22].val[0] = 0; - - Tuner->Init_Ctrl[23].Ctrl_Num = XTAL_CAPSELECT ; - Tuner->Init_Ctrl[23].size = 1 ; - Tuner->Init_Ctrl[23].addr[0] = 91; - Tuner->Init_Ctrl[23].bit[0] = 5; - Tuner->Init_Ctrl[23].val[0] = 1; - - Tuner->Init_Ctrl[24].Ctrl_Num = IF_SEL_DBL ; - Tuner->Init_Ctrl[24].size = 1 ; - Tuner->Init_Ctrl[24].addr[0] = 43; - Tuner->Init_Ctrl[24].bit[0] = 0; - Tuner->Init_Ctrl[24].val[0] = 1; - - Tuner->Init_Ctrl[25].Ctrl_Num = RFSYN_R_DIV ; - Tuner->Init_Ctrl[25].size = 2 ; - Tuner->Init_Ctrl[25].addr[0] = 22; - Tuner->Init_Ctrl[25].bit[0] = 0; - Tuner->Init_Ctrl[25].val[0] = 1; - Tuner->Init_Ctrl[25].addr[1] = 22; - Tuner->Init_Ctrl[25].bit[1] = 1; - Tuner->Init_Ctrl[25].val[1] = 1; - - Tuner->Init_Ctrl[26].Ctrl_Num = SEQ_EXTSYNTHCALIF ; - Tuner->Init_Ctrl[26].size = 1 ; - Tuner->Init_Ctrl[26].addr[0] = 134; - Tuner->Init_Ctrl[26].bit[0] = 2; - Tuner->Init_Ctrl[26].val[0] = 0; - - Tuner->Init_Ctrl[27].Ctrl_Num = SEQ_EXTDCCAL ; - Tuner->Init_Ctrl[27].size = 1 ; - Tuner->Init_Ctrl[27].addr[0] = 137; - Tuner->Init_Ctrl[27].bit[0] = 3; - Tuner->Init_Ctrl[27].val[0] = 0; - - Tuner->Init_Ctrl[28].Ctrl_Num = AGC_EN_RSSI ; - Tuner->Init_Ctrl[28].size = 1 ; - Tuner->Init_Ctrl[28].addr[0] = 77; - Tuner->Init_Ctrl[28].bit[0] = 7; - Tuner->Init_Ctrl[28].val[0] = 0; - - Tuner->Init_Ctrl[29].Ctrl_Num = RFA_ENCLKRFAGC ; - Tuner->Init_Ctrl[29].size = 1 ; - Tuner->Init_Ctrl[29].addr[0] = 166; - Tuner->Init_Ctrl[29].bit[0] = 7; - Tuner->Init_Ctrl[29].val[0] = 1; - - Tuner->Init_Ctrl[30].Ctrl_Num = RFA_RSSI_REFH ; - Tuner->Init_Ctrl[30].size = 3 ; - Tuner->Init_Ctrl[30].addr[0] = 166; - Tuner->Init_Ctrl[30].bit[0] = 0; - Tuner->Init_Ctrl[30].val[0] = 0; - Tuner->Init_Ctrl[30].addr[1] = 166; - Tuner->Init_Ctrl[30].bit[1] = 1; - Tuner->Init_Ctrl[30].val[1] = 1; - Tuner->Init_Ctrl[30].addr[2] = 166; - Tuner->Init_Ctrl[30].bit[2] = 2; - Tuner->Init_Ctrl[30].val[2] = 1; - - Tuner->Init_Ctrl[31].Ctrl_Num = RFA_RSSI_REF ; - Tuner->Init_Ctrl[31].size = 3 ; - Tuner->Init_Ctrl[31].addr[0] = 166; - Tuner->Init_Ctrl[31].bit[0] = 3; - Tuner->Init_Ctrl[31].val[0] = 1; - Tuner->Init_Ctrl[31].addr[1] = 166; - Tuner->Init_Ctrl[31].bit[1] = 4; - Tuner->Init_Ctrl[31].val[1] = 0; - Tuner->Init_Ctrl[31].addr[2] = 166; - Tuner->Init_Ctrl[31].bit[2] = 5; - Tuner->Init_Ctrl[31].val[2] = 1; - - Tuner->Init_Ctrl[32].Ctrl_Num = RFA_RSSI_REFL ; - Tuner->Init_Ctrl[32].size = 3 ; - Tuner->Init_Ctrl[32].addr[0] = 167; - Tuner->Init_Ctrl[32].bit[0] = 0; - Tuner->Init_Ctrl[32].val[0] = 1; - Tuner->Init_Ctrl[32].addr[1] = 167; - Tuner->Init_Ctrl[32].bit[1] = 1; - Tuner->Init_Ctrl[32].val[1] = 1; - Tuner->Init_Ctrl[32].addr[2] = 167; - Tuner->Init_Ctrl[32].bit[2] = 2; - Tuner->Init_Ctrl[32].val[2] = 0; - - Tuner->Init_Ctrl[33].Ctrl_Num = RFA_FLR ; - Tuner->Init_Ctrl[33].size = 4 ; - Tuner->Init_Ctrl[33].addr[0] = 168; - Tuner->Init_Ctrl[33].bit[0] = 0; - Tuner->Init_Ctrl[33].val[0] = 0; - Tuner->Init_Ctrl[33].addr[1] = 168; - Tuner->Init_Ctrl[33].bit[1] = 1; - Tuner->Init_Ctrl[33].val[1] = 1; - Tuner->Init_Ctrl[33].addr[2] = 168; - Tuner->Init_Ctrl[33].bit[2] = 2; - Tuner->Init_Ctrl[33].val[2] = 0; - Tuner->Init_Ctrl[33].addr[3] = 168; - Tuner->Init_Ctrl[33].bit[3] = 3; - Tuner->Init_Ctrl[33].val[3] = 0; - - Tuner->Init_Ctrl[34].Ctrl_Num = RFA_CEIL ; - Tuner->Init_Ctrl[34].size = 4 ; - Tuner->Init_Ctrl[34].addr[0] = 168; - Tuner->Init_Ctrl[34].bit[0] = 4; - Tuner->Init_Ctrl[34].val[0] = 1; - Tuner->Init_Ctrl[34].addr[1] = 168; - Tuner->Init_Ctrl[34].bit[1] = 5; - Tuner->Init_Ctrl[34].val[1] = 1; - Tuner->Init_Ctrl[34].addr[2] = 168; - Tuner->Init_Ctrl[34].bit[2] = 6; - Tuner->Init_Ctrl[34].val[2] = 1; - Tuner->Init_Ctrl[34].addr[3] = 168; - Tuner->Init_Ctrl[34].bit[3] = 7; - Tuner->Init_Ctrl[34].val[3] = 1; - - Tuner->Init_Ctrl[35].Ctrl_Num = SEQ_EXTIQFSMPULSE ; - Tuner->Init_Ctrl[35].size = 1 ; - Tuner->Init_Ctrl[35].addr[0] = 135; - Tuner->Init_Ctrl[35].bit[0] = 0; - Tuner->Init_Ctrl[35].val[0] = 0; - - Tuner->Init_Ctrl[36].Ctrl_Num = OVERRIDE_1 ; - Tuner->Init_Ctrl[36].size = 1 ; - Tuner->Init_Ctrl[36].addr[0] = 56; - Tuner->Init_Ctrl[36].bit[0] = 3; - Tuner->Init_Ctrl[36].val[0] = 0; - - Tuner->Init_Ctrl[37].Ctrl_Num = BB_INITSTATE_DLPF_TUNE ; - Tuner->Init_Ctrl[37].size = 7 ; - Tuner->Init_Ctrl[37].addr[0] = 59; - Tuner->Init_Ctrl[37].bit[0] = 1; - Tuner->Init_Ctrl[37].val[0] = 0; - Tuner->Init_Ctrl[37].addr[1] = 59; - Tuner->Init_Ctrl[37].bit[1] = 2; - Tuner->Init_Ctrl[37].val[1] = 0; - Tuner->Init_Ctrl[37].addr[2] = 59; - Tuner->Init_Ctrl[37].bit[2] = 3; - Tuner->Init_Ctrl[37].val[2] = 0; - Tuner->Init_Ctrl[37].addr[3] = 59; - Tuner->Init_Ctrl[37].bit[3] = 4; - Tuner->Init_Ctrl[37].val[3] = 0; - Tuner->Init_Ctrl[37].addr[4] = 59; - Tuner->Init_Ctrl[37].bit[4] = 5; - Tuner->Init_Ctrl[37].val[4] = 0; - Tuner->Init_Ctrl[37].addr[5] = 59; - Tuner->Init_Ctrl[37].bit[5] = 6; - Tuner->Init_Ctrl[37].val[5] = 0; - Tuner->Init_Ctrl[37].addr[6] = 59; - Tuner->Init_Ctrl[37].bit[6] = 7; - Tuner->Init_Ctrl[37].val[6] = 0; - - Tuner->Init_Ctrl[38].Ctrl_Num = TG_R_DIV ; - Tuner->Init_Ctrl[38].size = 6 ; - Tuner->Init_Ctrl[38].addr[0] = 32; - Tuner->Init_Ctrl[38].bit[0] = 2; - Tuner->Init_Ctrl[38].val[0] = 0; - Tuner->Init_Ctrl[38].addr[1] = 32; - Tuner->Init_Ctrl[38].bit[1] = 3; - Tuner->Init_Ctrl[38].val[1] = 0; - Tuner->Init_Ctrl[38].addr[2] = 32; - Tuner->Init_Ctrl[38].bit[2] = 4; - Tuner->Init_Ctrl[38].val[2] = 0; - Tuner->Init_Ctrl[38].addr[3] = 32; - Tuner->Init_Ctrl[38].bit[3] = 5; - Tuner->Init_Ctrl[38].val[3] = 0; - Tuner->Init_Ctrl[38].addr[4] = 32; - Tuner->Init_Ctrl[38].bit[4] = 6; - Tuner->Init_Ctrl[38].val[4] = 1; - Tuner->Init_Ctrl[38].addr[5] = 32; - Tuner->Init_Ctrl[38].bit[5] = 7; - Tuner->Init_Ctrl[38].val[5] = 0; - - Tuner->Init_Ctrl[39].Ctrl_Num = EN_CHP_LIN_B ; - Tuner->Init_Ctrl[39].size = 1 ; - Tuner->Init_Ctrl[39].addr[0] = 25; - Tuner->Init_Ctrl[39].bit[0] = 3; - Tuner->Init_Ctrl[39].val[0] = 1; - - - Tuner->CH_Ctrl_Num = CHCTRL_NUM ; - - Tuner->CH_Ctrl[0].Ctrl_Num = DN_POLY ; - Tuner->CH_Ctrl[0].size = 2 ; - Tuner->CH_Ctrl[0].addr[0] = 68; - Tuner->CH_Ctrl[0].bit[0] = 6; - Tuner->CH_Ctrl[0].val[0] = 1; - Tuner->CH_Ctrl[0].addr[1] = 68; - Tuner->CH_Ctrl[0].bit[1] = 7; - Tuner->CH_Ctrl[0].val[1] = 1; - - Tuner->CH_Ctrl[1].Ctrl_Num = DN_RFGAIN ; - Tuner->CH_Ctrl[1].size = 2 ; - Tuner->CH_Ctrl[1].addr[0] = 70; - Tuner->CH_Ctrl[1].bit[0] = 6; - Tuner->CH_Ctrl[1].val[0] = 1; - Tuner->CH_Ctrl[1].addr[1] = 70; - Tuner->CH_Ctrl[1].bit[1] = 7; - Tuner->CH_Ctrl[1].val[1] = 0; - - Tuner->CH_Ctrl[2].Ctrl_Num = DN_CAP_RFLPF ; - Tuner->CH_Ctrl[2].size = 9 ; - Tuner->CH_Ctrl[2].addr[0] = 69; - Tuner->CH_Ctrl[2].bit[0] = 5; - Tuner->CH_Ctrl[2].val[0] = 0; - Tuner->CH_Ctrl[2].addr[1] = 69; - Tuner->CH_Ctrl[2].bit[1] = 6; - Tuner->CH_Ctrl[2].val[1] = 0; - Tuner->CH_Ctrl[2].addr[2] = 69; - Tuner->CH_Ctrl[2].bit[2] = 7; - Tuner->CH_Ctrl[2].val[2] = 0; - Tuner->CH_Ctrl[2].addr[3] = 68; - Tuner->CH_Ctrl[2].bit[3] = 0; - Tuner->CH_Ctrl[2].val[3] = 0; - Tuner->CH_Ctrl[2].addr[4] = 68; - Tuner->CH_Ctrl[2].bit[4] = 1; - Tuner->CH_Ctrl[2].val[4] = 0; - Tuner->CH_Ctrl[2].addr[5] = 68; - Tuner->CH_Ctrl[2].bit[5] = 2; - Tuner->CH_Ctrl[2].val[5] = 0; - Tuner->CH_Ctrl[2].addr[6] = 68; - Tuner->CH_Ctrl[2].bit[6] = 3; - Tuner->CH_Ctrl[2].val[6] = 0; - Tuner->CH_Ctrl[2].addr[7] = 68; - Tuner->CH_Ctrl[2].bit[7] = 4; - Tuner->CH_Ctrl[2].val[7] = 0; - Tuner->CH_Ctrl[2].addr[8] = 68; - Tuner->CH_Ctrl[2].bit[8] = 5; - Tuner->CH_Ctrl[2].val[8] = 0; - - Tuner->CH_Ctrl[3].Ctrl_Num = DN_EN_VHFUHFBAR ; - Tuner->CH_Ctrl[3].size = 1 ; - Tuner->CH_Ctrl[3].addr[0] = 70; - Tuner->CH_Ctrl[3].bit[0] = 5; - Tuner->CH_Ctrl[3].val[0] = 0; - - Tuner->CH_Ctrl[4].Ctrl_Num = DN_GAIN_ADJUST ; - Tuner->CH_Ctrl[4].size = 3 ; - Tuner->CH_Ctrl[4].addr[0] = 73; - Tuner->CH_Ctrl[4].bit[0] = 4; - Tuner->CH_Ctrl[4].val[0] = 0; - Tuner->CH_Ctrl[4].addr[1] = 73; - Tuner->CH_Ctrl[4].bit[1] = 5; - Tuner->CH_Ctrl[4].val[1] = 1; - Tuner->CH_Ctrl[4].addr[2] = 73; - Tuner->CH_Ctrl[4].bit[2] = 6; - Tuner->CH_Ctrl[4].val[2] = 0; - - Tuner->CH_Ctrl[5].Ctrl_Num = DN_IQTNBUF_AMP ; - Tuner->CH_Ctrl[5].size = 4 ; - Tuner->CH_Ctrl[5].addr[0] = 70; - Tuner->CH_Ctrl[5].bit[0] = 0; - Tuner->CH_Ctrl[5].val[0] = 0; - Tuner->CH_Ctrl[5].addr[1] = 70; - Tuner->CH_Ctrl[5].bit[1] = 1; - Tuner->CH_Ctrl[5].val[1] = 0; - Tuner->CH_Ctrl[5].addr[2] = 70; - Tuner->CH_Ctrl[5].bit[2] = 2; - Tuner->CH_Ctrl[5].val[2] = 0; - Tuner->CH_Ctrl[5].addr[3] = 70; - Tuner->CH_Ctrl[5].bit[3] = 3; - Tuner->CH_Ctrl[5].val[3] = 0; - - Tuner->CH_Ctrl[6].Ctrl_Num = DN_IQTNGNBFBIAS_BST ; - Tuner->CH_Ctrl[6].size = 1 ; - Tuner->CH_Ctrl[6].addr[0] = 70; - Tuner->CH_Ctrl[6].bit[0] = 4; - Tuner->CH_Ctrl[6].val[0] = 1; - - Tuner->CH_Ctrl[7].Ctrl_Num = RFSYN_EN_OUTMUX ; - Tuner->CH_Ctrl[7].size = 1 ; - Tuner->CH_Ctrl[7].addr[0] = 111; - Tuner->CH_Ctrl[7].bit[0] = 4; - Tuner->CH_Ctrl[7].val[0] = 0; - - Tuner->CH_Ctrl[8].Ctrl_Num = RFSYN_SEL_VCO_OUT ; - Tuner->CH_Ctrl[8].size = 1 ; - Tuner->CH_Ctrl[8].addr[0] = 111; - Tuner->CH_Ctrl[8].bit[0] = 7; - Tuner->CH_Ctrl[8].val[0] = 1; - - Tuner->CH_Ctrl[9].Ctrl_Num = RFSYN_SEL_VCO_HI ; - Tuner->CH_Ctrl[9].size = 1 ; - Tuner->CH_Ctrl[9].addr[0] = 111; - Tuner->CH_Ctrl[9].bit[0] = 6; - Tuner->CH_Ctrl[9].val[0] = 1; - - Tuner->CH_Ctrl[10].Ctrl_Num = RFSYN_SEL_DIVM ; - Tuner->CH_Ctrl[10].size = 1 ; - Tuner->CH_Ctrl[10].addr[0] = 111; - Tuner->CH_Ctrl[10].bit[0] = 5; - Tuner->CH_Ctrl[10].val[0] = 0; - - Tuner->CH_Ctrl[11].Ctrl_Num = RFSYN_RF_DIV_BIAS ; - Tuner->CH_Ctrl[11].size = 2 ; - Tuner->CH_Ctrl[11].addr[0] = 110; - Tuner->CH_Ctrl[11].bit[0] = 0; - Tuner->CH_Ctrl[11].val[0] = 1; - Tuner->CH_Ctrl[11].addr[1] = 110; - Tuner->CH_Ctrl[11].bit[1] = 1; - Tuner->CH_Ctrl[11].val[1] = 0; - - Tuner->CH_Ctrl[12].Ctrl_Num = DN_SEL_FREQ ; - Tuner->CH_Ctrl[12].size = 3 ; - Tuner->CH_Ctrl[12].addr[0] = 69; - Tuner->CH_Ctrl[12].bit[0] = 2; - Tuner->CH_Ctrl[12].val[0] = 0; - Tuner->CH_Ctrl[12].addr[1] = 69; - Tuner->CH_Ctrl[12].bit[1] = 3; - Tuner->CH_Ctrl[12].val[1] = 0; - Tuner->CH_Ctrl[12].addr[2] = 69; - Tuner->CH_Ctrl[12].bit[2] = 4; - Tuner->CH_Ctrl[12].val[2] = 0; - - Tuner->CH_Ctrl[13].Ctrl_Num = RFSYN_VCO_BIAS ; - Tuner->CH_Ctrl[13].size = 6 ; - Tuner->CH_Ctrl[13].addr[0] = 110; - Tuner->CH_Ctrl[13].bit[0] = 2; - Tuner->CH_Ctrl[13].val[0] = 0; - Tuner->CH_Ctrl[13].addr[1] = 110; - Tuner->CH_Ctrl[13].bit[1] = 3; - Tuner->CH_Ctrl[13].val[1] = 0; - Tuner->CH_Ctrl[13].addr[2] = 110; - Tuner->CH_Ctrl[13].bit[2] = 4; - Tuner->CH_Ctrl[13].val[2] = 0; - Tuner->CH_Ctrl[13].addr[3] = 110; - Tuner->CH_Ctrl[13].bit[3] = 5; - Tuner->CH_Ctrl[13].val[3] = 0; - Tuner->CH_Ctrl[13].addr[4] = 110; - Tuner->CH_Ctrl[13].bit[4] = 6; - Tuner->CH_Ctrl[13].val[4] = 0; - Tuner->CH_Ctrl[13].addr[5] = 110; - Tuner->CH_Ctrl[13].bit[5] = 7; - Tuner->CH_Ctrl[13].val[5] = 1; - - Tuner->CH_Ctrl[14].Ctrl_Num = CHCAL_INT_MOD_RF ; - Tuner->CH_Ctrl[14].size = 7 ; - Tuner->CH_Ctrl[14].addr[0] = 14; - Tuner->CH_Ctrl[14].bit[0] = 0; - Tuner->CH_Ctrl[14].val[0] = 0; - Tuner->CH_Ctrl[14].addr[1] = 14; - Tuner->CH_Ctrl[14].bit[1] = 1; - Tuner->CH_Ctrl[14].val[1] = 0; - Tuner->CH_Ctrl[14].addr[2] = 14; - Tuner->CH_Ctrl[14].bit[2] = 2; - Tuner->CH_Ctrl[14].val[2] = 0; - Tuner->CH_Ctrl[14].addr[3] = 14; - Tuner->CH_Ctrl[14].bit[3] = 3; - Tuner->CH_Ctrl[14].val[3] = 0; - Tuner->CH_Ctrl[14].addr[4] = 14; - Tuner->CH_Ctrl[14].bit[4] = 4; - Tuner->CH_Ctrl[14].val[4] = 0; - Tuner->CH_Ctrl[14].addr[5] = 14; - Tuner->CH_Ctrl[14].bit[5] = 5; - Tuner->CH_Ctrl[14].val[5] = 0; - Tuner->CH_Ctrl[14].addr[6] = 14; - Tuner->CH_Ctrl[14].bit[6] = 6; - Tuner->CH_Ctrl[14].val[6] = 0; - - Tuner->CH_Ctrl[15].Ctrl_Num = CHCAL_FRAC_MOD_RF ; - Tuner->CH_Ctrl[15].size = 18 ; - Tuner->CH_Ctrl[15].addr[0] = 17; - Tuner->CH_Ctrl[15].bit[0] = 6; - Tuner->CH_Ctrl[15].val[0] = 0; - Tuner->CH_Ctrl[15].addr[1] = 17; - Tuner->CH_Ctrl[15].bit[1] = 7; - Tuner->CH_Ctrl[15].val[1] = 0; - Tuner->CH_Ctrl[15].addr[2] = 16; - Tuner->CH_Ctrl[15].bit[2] = 0; - Tuner->CH_Ctrl[15].val[2] = 0; - Tuner->CH_Ctrl[15].addr[3] = 16; - Tuner->CH_Ctrl[15].bit[3] = 1; - Tuner->CH_Ctrl[15].val[3] = 0; - Tuner->CH_Ctrl[15].addr[4] = 16; - Tuner->CH_Ctrl[15].bit[4] = 2; - Tuner->CH_Ctrl[15].val[4] = 0; - Tuner->CH_Ctrl[15].addr[5] = 16; - Tuner->CH_Ctrl[15].bit[5] = 3; - Tuner->CH_Ctrl[15].val[5] = 0; - Tuner->CH_Ctrl[15].addr[6] = 16; - Tuner->CH_Ctrl[15].bit[6] = 4; - Tuner->CH_Ctrl[15].val[6] = 0; - Tuner->CH_Ctrl[15].addr[7] = 16; - Tuner->CH_Ctrl[15].bit[7] = 5; - Tuner->CH_Ctrl[15].val[7] = 0; - Tuner->CH_Ctrl[15].addr[8] = 16; - Tuner->CH_Ctrl[15].bit[8] = 6; - Tuner->CH_Ctrl[15].val[8] = 0; - Tuner->CH_Ctrl[15].addr[9] = 16; - Tuner->CH_Ctrl[15].bit[9] = 7; - Tuner->CH_Ctrl[15].val[9] = 0; - Tuner->CH_Ctrl[15].addr[10] = 15; - Tuner->CH_Ctrl[15].bit[10] = 0; - Tuner->CH_Ctrl[15].val[10] = 0; - Tuner->CH_Ctrl[15].addr[11] = 15; - Tuner->CH_Ctrl[15].bit[11] = 1; - Tuner->CH_Ctrl[15].val[11] = 0; - Tuner->CH_Ctrl[15].addr[12] = 15; - Tuner->CH_Ctrl[15].bit[12] = 2; - Tuner->CH_Ctrl[15].val[12] = 0; - Tuner->CH_Ctrl[15].addr[13] = 15; - Tuner->CH_Ctrl[15].bit[13] = 3; - Tuner->CH_Ctrl[15].val[13] = 0; - Tuner->CH_Ctrl[15].addr[14] = 15; - Tuner->CH_Ctrl[15].bit[14] = 4; - Tuner->CH_Ctrl[15].val[14] = 0; - Tuner->CH_Ctrl[15].addr[15] = 15; - Tuner->CH_Ctrl[15].bit[15] = 5; - Tuner->CH_Ctrl[15].val[15] = 0; - Tuner->CH_Ctrl[15].addr[16] = 15; - Tuner->CH_Ctrl[15].bit[16] = 6; - Tuner->CH_Ctrl[15].val[16] = 1; - Tuner->CH_Ctrl[15].addr[17] = 15; - Tuner->CH_Ctrl[15].bit[17] = 7; - Tuner->CH_Ctrl[15].val[17] = 1; - - Tuner->CH_Ctrl[16].Ctrl_Num = RFSYN_LPF_R ; - Tuner->CH_Ctrl[16].size = 5 ; - Tuner->CH_Ctrl[16].addr[0] = 112; - Tuner->CH_Ctrl[16].bit[0] = 0; - Tuner->CH_Ctrl[16].val[0] = 0; - Tuner->CH_Ctrl[16].addr[1] = 112; - Tuner->CH_Ctrl[16].bit[1] = 1; - Tuner->CH_Ctrl[16].val[1] = 0; - Tuner->CH_Ctrl[16].addr[2] = 112; - Tuner->CH_Ctrl[16].bit[2] = 2; - Tuner->CH_Ctrl[16].val[2] = 0; - Tuner->CH_Ctrl[16].addr[3] = 112; - Tuner->CH_Ctrl[16].bit[3] = 3; - Tuner->CH_Ctrl[16].val[3] = 0; - Tuner->CH_Ctrl[16].addr[4] = 112; - Tuner->CH_Ctrl[16].bit[4] = 4; - Tuner->CH_Ctrl[16].val[4] = 1; - - Tuner->CH_Ctrl[17].Ctrl_Num = CHCAL_EN_INT_RF ; - Tuner->CH_Ctrl[17].size = 1 ; - Tuner->CH_Ctrl[17].addr[0] = 14; - Tuner->CH_Ctrl[17].bit[0] = 7; - Tuner->CH_Ctrl[17].val[0] = 0; - - Tuner->CH_Ctrl[18].Ctrl_Num = TG_LO_DIVVAL ; - Tuner->CH_Ctrl[18].size = 4 ; - Tuner->CH_Ctrl[18].addr[0] = 107; - Tuner->CH_Ctrl[18].bit[0] = 3; - Tuner->CH_Ctrl[18].val[0] = 0; - Tuner->CH_Ctrl[18].addr[1] = 107; - Tuner->CH_Ctrl[18].bit[1] = 4; - Tuner->CH_Ctrl[18].val[1] = 0; - Tuner->CH_Ctrl[18].addr[2] = 107; - Tuner->CH_Ctrl[18].bit[2] = 5; - Tuner->CH_Ctrl[18].val[2] = 0; - Tuner->CH_Ctrl[18].addr[3] = 107; - Tuner->CH_Ctrl[18].bit[3] = 6; - Tuner->CH_Ctrl[18].val[3] = 0; - - Tuner->CH_Ctrl[19].Ctrl_Num = TG_LO_SELVAL ; - Tuner->CH_Ctrl[19].size = 3 ; - Tuner->CH_Ctrl[19].addr[0] = 107; - Tuner->CH_Ctrl[19].bit[0] = 7; - Tuner->CH_Ctrl[19].val[0] = 1; - Tuner->CH_Ctrl[19].addr[1] = 106; - Tuner->CH_Ctrl[19].bit[1] = 0; - Tuner->CH_Ctrl[19].val[1] = 1; - Tuner->CH_Ctrl[19].addr[2] = 106; - Tuner->CH_Ctrl[19].bit[2] = 1; - Tuner->CH_Ctrl[19].val[2] = 1; - - Tuner->CH_Ctrl[20].Ctrl_Num = TG_DIV_VAL ; - Tuner->CH_Ctrl[20].size = 11 ; - Tuner->CH_Ctrl[20].addr[0] = 109; - Tuner->CH_Ctrl[20].bit[0] = 2; - Tuner->CH_Ctrl[20].val[0] = 0; - Tuner->CH_Ctrl[20].addr[1] = 109; - Tuner->CH_Ctrl[20].bit[1] = 3; - Tuner->CH_Ctrl[20].val[1] = 0; - Tuner->CH_Ctrl[20].addr[2] = 109; - Tuner->CH_Ctrl[20].bit[2] = 4; - Tuner->CH_Ctrl[20].val[2] = 0; - Tuner->CH_Ctrl[20].addr[3] = 109; - Tuner->CH_Ctrl[20].bit[3] = 5; - Tuner->CH_Ctrl[20].val[3] = 0; - Tuner->CH_Ctrl[20].addr[4] = 109; - Tuner->CH_Ctrl[20].bit[4] = 6; - Tuner->CH_Ctrl[20].val[4] = 0; - Tuner->CH_Ctrl[20].addr[5] = 109; - Tuner->CH_Ctrl[20].bit[5] = 7; - Tuner->CH_Ctrl[20].val[5] = 0; - Tuner->CH_Ctrl[20].addr[6] = 108; - Tuner->CH_Ctrl[20].bit[6] = 0; - Tuner->CH_Ctrl[20].val[6] = 0; - Tuner->CH_Ctrl[20].addr[7] = 108; - Tuner->CH_Ctrl[20].bit[7] = 1; - Tuner->CH_Ctrl[20].val[7] = 0; - Tuner->CH_Ctrl[20].addr[8] = 108; - Tuner->CH_Ctrl[20].bit[8] = 2; - Tuner->CH_Ctrl[20].val[8] = 1; - Tuner->CH_Ctrl[20].addr[9] = 108; - Tuner->CH_Ctrl[20].bit[9] = 3; - Tuner->CH_Ctrl[20].val[9] = 1; - Tuner->CH_Ctrl[20].addr[10] = 108; - Tuner->CH_Ctrl[20].bit[10] = 4; - Tuner->CH_Ctrl[20].val[10] = 1; - - Tuner->CH_Ctrl[21].Ctrl_Num = TG_VCO_BIAS ; - Tuner->CH_Ctrl[21].size = 6 ; - Tuner->CH_Ctrl[21].addr[0] = 106; - Tuner->CH_Ctrl[21].bit[0] = 2; - Tuner->CH_Ctrl[21].val[0] = 0; - Tuner->CH_Ctrl[21].addr[1] = 106; - Tuner->CH_Ctrl[21].bit[1] = 3; - Tuner->CH_Ctrl[21].val[1] = 0; - Tuner->CH_Ctrl[21].addr[2] = 106; - Tuner->CH_Ctrl[21].bit[2] = 4; - Tuner->CH_Ctrl[21].val[2] = 0; - Tuner->CH_Ctrl[21].addr[3] = 106; - Tuner->CH_Ctrl[21].bit[3] = 5; - Tuner->CH_Ctrl[21].val[3] = 0; - Tuner->CH_Ctrl[21].addr[4] = 106; - Tuner->CH_Ctrl[21].bit[4] = 6; - Tuner->CH_Ctrl[21].val[4] = 0; - Tuner->CH_Ctrl[21].addr[5] = 106; - Tuner->CH_Ctrl[21].bit[5] = 7; - Tuner->CH_Ctrl[21].val[5] = 1; - - Tuner->CH_Ctrl[22].Ctrl_Num = SEQ_EXTPOWERUP ; - Tuner->CH_Ctrl[22].size = 1 ; - Tuner->CH_Ctrl[22].addr[0] = 138; - Tuner->CH_Ctrl[22].bit[0] = 4; - Tuner->CH_Ctrl[22].val[0] = 1; - - Tuner->CH_Ctrl[23].Ctrl_Num = OVERRIDE_2 ; - Tuner->CH_Ctrl[23].size = 1 ; - Tuner->CH_Ctrl[23].addr[0] = 17; - Tuner->CH_Ctrl[23].bit[0] = 5; - Tuner->CH_Ctrl[23].val[0] = 0; - - Tuner->CH_Ctrl[24].Ctrl_Num = OVERRIDE_3 ; - Tuner->CH_Ctrl[24].size = 1 ; - Tuner->CH_Ctrl[24].addr[0] = 111; - Tuner->CH_Ctrl[24].bit[0] = 3; - Tuner->CH_Ctrl[24].val[0] = 0; - - Tuner->CH_Ctrl[25].Ctrl_Num = OVERRIDE_4 ; - Tuner->CH_Ctrl[25].size = 1 ; - Tuner->CH_Ctrl[25].addr[0] = 112; - Tuner->CH_Ctrl[25].bit[0] = 7; - Tuner->CH_Ctrl[25].val[0] = 0; - - Tuner->CH_Ctrl[26].Ctrl_Num = SEQ_FSM_PULSE ; - Tuner->CH_Ctrl[26].size = 1 ; - Tuner->CH_Ctrl[26].addr[0] = 136; - Tuner->CH_Ctrl[26].bit[0] = 7; - Tuner->CH_Ctrl[26].val[0] = 0; - - Tuner->CH_Ctrl[27].Ctrl_Num = GPIO_4B ; - Tuner->CH_Ctrl[27].size = 1 ; - Tuner->CH_Ctrl[27].addr[0] = 149; - Tuner->CH_Ctrl[27].bit[0] = 7; - Tuner->CH_Ctrl[27].val[0] = 0; - - Tuner->CH_Ctrl[28].Ctrl_Num = GPIO_3B ; - Tuner->CH_Ctrl[28].size = 1 ; - Tuner->CH_Ctrl[28].addr[0] = 149; - Tuner->CH_Ctrl[28].bit[0] = 6; - Tuner->CH_Ctrl[28].val[0] = 0; - - Tuner->CH_Ctrl[29].Ctrl_Num = GPIO_4 ; - Tuner->CH_Ctrl[29].size = 1 ; - Tuner->CH_Ctrl[29].addr[0] = 149; - Tuner->CH_Ctrl[29].bit[0] = 5; - Tuner->CH_Ctrl[29].val[0] = 1; - - Tuner->CH_Ctrl[30].Ctrl_Num = GPIO_3 ; - Tuner->CH_Ctrl[30].size = 1 ; - Tuner->CH_Ctrl[30].addr[0] = 149; - Tuner->CH_Ctrl[30].bit[0] = 4; - Tuner->CH_Ctrl[30].val[0] = 1; - - Tuner->CH_Ctrl[31].Ctrl_Num = GPIO_1B ; - Tuner->CH_Ctrl[31].size = 1 ; - Tuner->CH_Ctrl[31].addr[0] = 149; - Tuner->CH_Ctrl[31].bit[0] = 3; - Tuner->CH_Ctrl[31].val[0] = 0; - - Tuner->CH_Ctrl[32].Ctrl_Num = DAC_A_ENABLE ; - Tuner->CH_Ctrl[32].size = 1 ; - Tuner->CH_Ctrl[32].addr[0] = 93; - Tuner->CH_Ctrl[32].bit[0] = 1; - Tuner->CH_Ctrl[32].val[0] = 0; - - Tuner->CH_Ctrl[33].Ctrl_Num = DAC_B_ENABLE ; - Tuner->CH_Ctrl[33].size = 1 ; - Tuner->CH_Ctrl[33].addr[0] = 93; - Tuner->CH_Ctrl[33].bit[0] = 0; - Tuner->CH_Ctrl[33].val[0] = 0; - - Tuner->CH_Ctrl[34].Ctrl_Num = DAC_DIN_A ; - Tuner->CH_Ctrl[34].size = 6 ; - Tuner->CH_Ctrl[34].addr[0] = 92; - Tuner->CH_Ctrl[34].bit[0] = 2; - Tuner->CH_Ctrl[34].val[0] = 0; - Tuner->CH_Ctrl[34].addr[1] = 92; - Tuner->CH_Ctrl[34].bit[1] = 3; - Tuner->CH_Ctrl[34].val[1] = 0; - Tuner->CH_Ctrl[34].addr[2] = 92; - Tuner->CH_Ctrl[34].bit[2] = 4; - Tuner->CH_Ctrl[34].val[2] = 0; - Tuner->CH_Ctrl[34].addr[3] = 92; - Tuner->CH_Ctrl[34].bit[3] = 5; - Tuner->CH_Ctrl[34].val[3] = 0; - Tuner->CH_Ctrl[34].addr[4] = 92; - Tuner->CH_Ctrl[34].bit[4] = 6; - Tuner->CH_Ctrl[34].val[4] = 0; - Tuner->CH_Ctrl[34].addr[5] = 92; - Tuner->CH_Ctrl[34].bit[5] = 7; - Tuner->CH_Ctrl[34].val[5] = 0; - - Tuner->CH_Ctrl[35].Ctrl_Num = DAC_DIN_B ; - Tuner->CH_Ctrl[35].size = 6 ; - Tuner->CH_Ctrl[35].addr[0] = 93; - Tuner->CH_Ctrl[35].bit[0] = 2; - Tuner->CH_Ctrl[35].val[0] = 0; - Tuner->CH_Ctrl[35].addr[1] = 93; - Tuner->CH_Ctrl[35].bit[1] = 3; - Tuner->CH_Ctrl[35].val[1] = 0; - Tuner->CH_Ctrl[35].addr[2] = 93; - Tuner->CH_Ctrl[35].bit[2] = 4; - Tuner->CH_Ctrl[35].val[2] = 0; - Tuner->CH_Ctrl[35].addr[3] = 93; - Tuner->CH_Ctrl[35].bit[3] = 5; - Tuner->CH_Ctrl[35].val[3] = 0; - Tuner->CH_Ctrl[35].addr[4] = 93; - Tuner->CH_Ctrl[35].bit[4] = 6; - Tuner->CH_Ctrl[35].val[4] = 0; - Tuner->CH_Ctrl[35].addr[5] = 93; - Tuner->CH_Ctrl[35].bit[5] = 7; - Tuner->CH_Ctrl[35].val[5] = 0; + struct mxl5005s_state *state = fe->demodulator_priv; + state->Init_Ctrl_Num = INITCTRL_NUM; + + state->Init_Ctrl[0].Ctrl_Num = DN_IQTN_AMP_CUT ; + state->Init_Ctrl[0].size = 1 ; + state->Init_Ctrl[0].addr[0] = 73; + state->Init_Ctrl[0].bit[0] = 7; + state->Init_Ctrl[0].val[0] = 0; + + state->Init_Ctrl[1].Ctrl_Num = BB_MODE ; + state->Init_Ctrl[1].size = 1 ; + state->Init_Ctrl[1].addr[0] = 53; + state->Init_Ctrl[1].bit[0] = 2; + state->Init_Ctrl[1].val[0] = 1; + + state->Init_Ctrl[2].Ctrl_Num = BB_BUF ; + state->Init_Ctrl[2].size = 2 ; + state->Init_Ctrl[2].addr[0] = 53; + state->Init_Ctrl[2].bit[0] = 1; + state->Init_Ctrl[2].val[0] = 0; + state->Init_Ctrl[2].addr[1] = 57; + state->Init_Ctrl[2].bit[1] = 0; + state->Init_Ctrl[2].val[1] = 1; + + state->Init_Ctrl[3].Ctrl_Num = BB_BUF_OA ; + state->Init_Ctrl[3].size = 1 ; + state->Init_Ctrl[3].addr[0] = 53; + state->Init_Ctrl[3].bit[0] = 0; + state->Init_Ctrl[3].val[0] = 0; + + state->Init_Ctrl[4].Ctrl_Num = BB_ALPF_BANDSELECT ; + state->Init_Ctrl[4].size = 3 ; + state->Init_Ctrl[4].addr[0] = 53; + state->Init_Ctrl[4].bit[0] = 5; + state->Init_Ctrl[4].val[0] = 0; + state->Init_Ctrl[4].addr[1] = 53; + state->Init_Ctrl[4].bit[1] = 6; + state->Init_Ctrl[4].val[1] = 0; + state->Init_Ctrl[4].addr[2] = 53; + state->Init_Ctrl[4].bit[2] = 7; + state->Init_Ctrl[4].val[2] = 1; + + state->Init_Ctrl[5].Ctrl_Num = BB_IQSWAP ; + state->Init_Ctrl[5].size = 1 ; + state->Init_Ctrl[5].addr[0] = 59; + state->Init_Ctrl[5].bit[0] = 0; + state->Init_Ctrl[5].val[0] = 0; + + state->Init_Ctrl[6].Ctrl_Num = BB_DLPF_BANDSEL ; + state->Init_Ctrl[6].size = 2 ; + state->Init_Ctrl[6].addr[0] = 53; + state->Init_Ctrl[6].bit[0] = 3; + state->Init_Ctrl[6].val[0] = 0; + state->Init_Ctrl[6].addr[1] = 53; + state->Init_Ctrl[6].bit[1] = 4; + state->Init_Ctrl[6].val[1] = 1; + + state->Init_Ctrl[7].Ctrl_Num = RFSYN_CHP_GAIN ; + state->Init_Ctrl[7].size = 4 ; + state->Init_Ctrl[7].addr[0] = 22; + state->Init_Ctrl[7].bit[0] = 4; + state->Init_Ctrl[7].val[0] = 0; + state->Init_Ctrl[7].addr[1] = 22; + state->Init_Ctrl[7].bit[1] = 5; + state->Init_Ctrl[7].val[1] = 1; + state->Init_Ctrl[7].addr[2] = 22; + state->Init_Ctrl[7].bit[2] = 6; + state->Init_Ctrl[7].val[2] = 1; + state->Init_Ctrl[7].addr[3] = 22; + state->Init_Ctrl[7].bit[3] = 7; + state->Init_Ctrl[7].val[3] = 0; + + state->Init_Ctrl[8].Ctrl_Num = RFSYN_EN_CHP_HIGAIN ; + state->Init_Ctrl[8].size = 1 ; + state->Init_Ctrl[8].addr[0] = 22; + state->Init_Ctrl[8].bit[0] = 2; + state->Init_Ctrl[8].val[0] = 0; + + state->Init_Ctrl[9].Ctrl_Num = AGC_IF ; + state->Init_Ctrl[9].size = 4 ; + state->Init_Ctrl[9].addr[0] = 76; + state->Init_Ctrl[9].bit[0] = 0; + state->Init_Ctrl[9].val[0] = 1; + state->Init_Ctrl[9].addr[1] = 76; + state->Init_Ctrl[9].bit[1] = 1; + state->Init_Ctrl[9].val[1] = 1; + state->Init_Ctrl[9].addr[2] = 76; + state->Init_Ctrl[9].bit[2] = 2; + state->Init_Ctrl[9].val[2] = 0; + state->Init_Ctrl[9].addr[3] = 76; + state->Init_Ctrl[9].bit[3] = 3; + state->Init_Ctrl[9].val[3] = 1; + + state->Init_Ctrl[10].Ctrl_Num = AGC_RF ; + state->Init_Ctrl[10].size = 4 ; + state->Init_Ctrl[10].addr[0] = 76; + state->Init_Ctrl[10].bit[0] = 4; + state->Init_Ctrl[10].val[0] = 1; + state->Init_Ctrl[10].addr[1] = 76; + state->Init_Ctrl[10].bit[1] = 5; + state->Init_Ctrl[10].val[1] = 1; + state->Init_Ctrl[10].addr[2] = 76; + state->Init_Ctrl[10].bit[2] = 6; + state->Init_Ctrl[10].val[2] = 0; + state->Init_Ctrl[10].addr[3] = 76; + state->Init_Ctrl[10].bit[3] = 7; + state->Init_Ctrl[10].val[3] = 1; + + state->Init_Ctrl[11].Ctrl_Num = IF_DIVVAL ; + state->Init_Ctrl[11].size = 5 ; + state->Init_Ctrl[11].addr[0] = 43; + state->Init_Ctrl[11].bit[0] = 3; + state->Init_Ctrl[11].val[0] = 0; + state->Init_Ctrl[11].addr[1] = 43; + state->Init_Ctrl[11].bit[1] = 4; + state->Init_Ctrl[11].val[1] = 0; + state->Init_Ctrl[11].addr[2] = 43; + state->Init_Ctrl[11].bit[2] = 5; + state->Init_Ctrl[11].val[2] = 0; + state->Init_Ctrl[11].addr[3] = 43; + state->Init_Ctrl[11].bit[3] = 6; + state->Init_Ctrl[11].val[3] = 1; + state->Init_Ctrl[11].addr[4] = 43; + state->Init_Ctrl[11].bit[4] = 7; + state->Init_Ctrl[11].val[4] = 0; + + state->Init_Ctrl[12].Ctrl_Num = IF_VCO_BIAS ; + state->Init_Ctrl[12].size = 6 ; + state->Init_Ctrl[12].addr[0] = 44; + state->Init_Ctrl[12].bit[0] = 2; + state->Init_Ctrl[12].val[0] = 0; + state->Init_Ctrl[12].addr[1] = 44; + state->Init_Ctrl[12].bit[1] = 3; + state->Init_Ctrl[12].val[1] = 0; + state->Init_Ctrl[12].addr[2] = 44; + state->Init_Ctrl[12].bit[2] = 4; + state->Init_Ctrl[12].val[2] = 0; + state->Init_Ctrl[12].addr[3] = 44; + state->Init_Ctrl[12].bit[3] = 5; + state->Init_Ctrl[12].val[3] = 1; + state->Init_Ctrl[12].addr[4] = 44; + state->Init_Ctrl[12].bit[4] = 6; + state->Init_Ctrl[12].val[4] = 0; + state->Init_Ctrl[12].addr[5] = 44; + state->Init_Ctrl[12].bit[5] = 7; + state->Init_Ctrl[12].val[5] = 0; + + state->Init_Ctrl[13].Ctrl_Num = CHCAL_INT_MOD_IF ; + state->Init_Ctrl[13].size = 7 ; + state->Init_Ctrl[13].addr[0] = 11; + state->Init_Ctrl[13].bit[0] = 0; + state->Init_Ctrl[13].val[0] = 1; + state->Init_Ctrl[13].addr[1] = 11; + state->Init_Ctrl[13].bit[1] = 1; + state->Init_Ctrl[13].val[1] = 0; + state->Init_Ctrl[13].addr[2] = 11; + state->Init_Ctrl[13].bit[2] = 2; + state->Init_Ctrl[13].val[2] = 0; + state->Init_Ctrl[13].addr[3] = 11; + state->Init_Ctrl[13].bit[3] = 3; + state->Init_Ctrl[13].val[3] = 1; + state->Init_Ctrl[13].addr[4] = 11; + state->Init_Ctrl[13].bit[4] = 4; + state->Init_Ctrl[13].val[4] = 1; + state->Init_Ctrl[13].addr[5] = 11; + state->Init_Ctrl[13].bit[5] = 5; + state->Init_Ctrl[13].val[5] = 0; + state->Init_Ctrl[13].addr[6] = 11; + state->Init_Ctrl[13].bit[6] = 6; + state->Init_Ctrl[13].val[6] = 0; + + state->Init_Ctrl[14].Ctrl_Num = CHCAL_FRAC_MOD_IF ; + state->Init_Ctrl[14].size = 16 ; + state->Init_Ctrl[14].addr[0] = 13; + state->Init_Ctrl[14].bit[0] = 0; + state->Init_Ctrl[14].val[0] = 0; + state->Init_Ctrl[14].addr[1] = 13; + state->Init_Ctrl[14].bit[1] = 1; + state->Init_Ctrl[14].val[1] = 0; + state->Init_Ctrl[14].addr[2] = 13; + state->Init_Ctrl[14].bit[2] = 2; + state->Init_Ctrl[14].val[2] = 0; + state->Init_Ctrl[14].addr[3] = 13; + state->Init_Ctrl[14].bit[3] = 3; + state->Init_Ctrl[14].val[3] = 0; + state->Init_Ctrl[14].addr[4] = 13; + state->Init_Ctrl[14].bit[4] = 4; + state->Init_Ctrl[14].val[4] = 0; + state->Init_Ctrl[14].addr[5] = 13; + state->Init_Ctrl[14].bit[5] = 5; + state->Init_Ctrl[14].val[5] = 0; + state->Init_Ctrl[14].addr[6] = 13; + state->Init_Ctrl[14].bit[6] = 6; + state->Init_Ctrl[14].val[6] = 0; + state->Init_Ctrl[14].addr[7] = 13; + state->Init_Ctrl[14].bit[7] = 7; + state->Init_Ctrl[14].val[7] = 0; + state->Init_Ctrl[14].addr[8] = 12; + state->Init_Ctrl[14].bit[8] = 0; + state->Init_Ctrl[14].val[8] = 0; + state->Init_Ctrl[14].addr[9] = 12; + state->Init_Ctrl[14].bit[9] = 1; + state->Init_Ctrl[14].val[9] = 0; + state->Init_Ctrl[14].addr[10] = 12; + state->Init_Ctrl[14].bit[10] = 2; + state->Init_Ctrl[14].val[10] = 0; + state->Init_Ctrl[14].addr[11] = 12; + state->Init_Ctrl[14].bit[11] = 3; + state->Init_Ctrl[14].val[11] = 0; + state->Init_Ctrl[14].addr[12] = 12; + state->Init_Ctrl[14].bit[12] = 4; + state->Init_Ctrl[14].val[12] = 0; + state->Init_Ctrl[14].addr[13] = 12; + state->Init_Ctrl[14].bit[13] = 5; + state->Init_Ctrl[14].val[13] = 1; + state->Init_Ctrl[14].addr[14] = 12; + state->Init_Ctrl[14].bit[14] = 6; + state->Init_Ctrl[14].val[14] = 1; + state->Init_Ctrl[14].addr[15] = 12; + state->Init_Ctrl[14].bit[15] = 7; + state->Init_Ctrl[14].val[15] = 0; + + state->Init_Ctrl[15].Ctrl_Num = DRV_RES_SEL ; + state->Init_Ctrl[15].size = 3 ; + state->Init_Ctrl[15].addr[0] = 147; + state->Init_Ctrl[15].bit[0] = 2; + state->Init_Ctrl[15].val[0] = 0; + state->Init_Ctrl[15].addr[1] = 147; + state->Init_Ctrl[15].bit[1] = 3; + state->Init_Ctrl[15].val[1] = 1; + state->Init_Ctrl[15].addr[2] = 147; + state->Init_Ctrl[15].bit[2] = 4; + state->Init_Ctrl[15].val[2] = 1; + + state->Init_Ctrl[16].Ctrl_Num = I_DRIVER ; + state->Init_Ctrl[16].size = 2 ; + state->Init_Ctrl[16].addr[0] = 147; + state->Init_Ctrl[16].bit[0] = 0; + state->Init_Ctrl[16].val[0] = 0; + state->Init_Ctrl[16].addr[1] = 147; + state->Init_Ctrl[16].bit[1] = 1; + state->Init_Ctrl[16].val[1] = 1; + + state->Init_Ctrl[17].Ctrl_Num = EN_AAF ; + state->Init_Ctrl[17].size = 1 ; + state->Init_Ctrl[17].addr[0] = 147; + state->Init_Ctrl[17].bit[0] = 7; + state->Init_Ctrl[17].val[0] = 0; + + state->Init_Ctrl[18].Ctrl_Num = EN_3P ; + state->Init_Ctrl[18].size = 1 ; + state->Init_Ctrl[18].addr[0] = 147; + state->Init_Ctrl[18].bit[0] = 6; + state->Init_Ctrl[18].val[0] = 0; + + state->Init_Ctrl[19].Ctrl_Num = EN_AUX_3P ; + state->Init_Ctrl[19].size = 1 ; + state->Init_Ctrl[19].addr[0] = 156; + state->Init_Ctrl[19].bit[0] = 0; + state->Init_Ctrl[19].val[0] = 0; + + state->Init_Ctrl[20].Ctrl_Num = SEL_AAF_BAND ; + state->Init_Ctrl[20].size = 1 ; + state->Init_Ctrl[20].addr[0] = 147; + state->Init_Ctrl[20].bit[0] = 5; + state->Init_Ctrl[20].val[0] = 0; + + state->Init_Ctrl[21].Ctrl_Num = SEQ_ENCLK16_CLK_OUT ; + state->Init_Ctrl[21].size = 1 ; + state->Init_Ctrl[21].addr[0] = 137; + state->Init_Ctrl[21].bit[0] = 4; + state->Init_Ctrl[21].val[0] = 0; + + state->Init_Ctrl[22].Ctrl_Num = SEQ_SEL4_16B ; + state->Init_Ctrl[22].size = 1 ; + state->Init_Ctrl[22].addr[0] = 137; + state->Init_Ctrl[22].bit[0] = 7; + state->Init_Ctrl[22].val[0] = 0; + + state->Init_Ctrl[23].Ctrl_Num = XTAL_CAPSELECT ; + state->Init_Ctrl[23].size = 1 ; + state->Init_Ctrl[23].addr[0] = 91; + state->Init_Ctrl[23].bit[0] = 5; + state->Init_Ctrl[23].val[0] = 1; + + state->Init_Ctrl[24].Ctrl_Num = IF_SEL_DBL ; + state->Init_Ctrl[24].size = 1 ; + state->Init_Ctrl[24].addr[0] = 43; + state->Init_Ctrl[24].bit[0] = 0; + state->Init_Ctrl[24].val[0] = 1; + + state->Init_Ctrl[25].Ctrl_Num = RFSYN_R_DIV ; + state->Init_Ctrl[25].size = 2 ; + state->Init_Ctrl[25].addr[0] = 22; + state->Init_Ctrl[25].bit[0] = 0; + state->Init_Ctrl[25].val[0] = 1; + state->Init_Ctrl[25].addr[1] = 22; + state->Init_Ctrl[25].bit[1] = 1; + state->Init_Ctrl[25].val[1] = 1; + + state->Init_Ctrl[26].Ctrl_Num = SEQ_EXTSYNTHCALIF ; + state->Init_Ctrl[26].size = 1 ; + state->Init_Ctrl[26].addr[0] = 134; + state->Init_Ctrl[26].bit[0] = 2; + state->Init_Ctrl[26].val[0] = 0; + + state->Init_Ctrl[27].Ctrl_Num = SEQ_EXTDCCAL ; + state->Init_Ctrl[27].size = 1 ; + state->Init_Ctrl[27].addr[0] = 137; + state->Init_Ctrl[27].bit[0] = 3; + state->Init_Ctrl[27].val[0] = 0; + + state->Init_Ctrl[28].Ctrl_Num = AGC_EN_RSSI ; + state->Init_Ctrl[28].size = 1 ; + state->Init_Ctrl[28].addr[0] = 77; + state->Init_Ctrl[28].bit[0] = 7; + state->Init_Ctrl[28].val[0] = 0; + + state->Init_Ctrl[29].Ctrl_Num = RFA_ENCLKRFAGC ; + state->Init_Ctrl[29].size = 1 ; + state->Init_Ctrl[29].addr[0] = 166; + state->Init_Ctrl[29].bit[0] = 7; + state->Init_Ctrl[29].val[0] = 1; + + state->Init_Ctrl[30].Ctrl_Num = RFA_RSSI_REFH ; + state->Init_Ctrl[30].size = 3 ; + state->Init_Ctrl[30].addr[0] = 166; + state->Init_Ctrl[30].bit[0] = 0; + state->Init_Ctrl[30].val[0] = 0; + state->Init_Ctrl[30].addr[1] = 166; + state->Init_Ctrl[30].bit[1] = 1; + state->Init_Ctrl[30].val[1] = 1; + state->Init_Ctrl[30].addr[2] = 166; + state->Init_Ctrl[30].bit[2] = 2; + state->Init_Ctrl[30].val[2] = 1; + + state->Init_Ctrl[31].Ctrl_Num = RFA_RSSI_REF ; + state->Init_Ctrl[31].size = 3 ; + state->Init_Ctrl[31].addr[0] = 166; + state->Init_Ctrl[31].bit[0] = 3; + state->Init_Ctrl[31].val[0] = 1; + state->Init_Ctrl[31].addr[1] = 166; + state->Init_Ctrl[31].bit[1] = 4; + state->Init_Ctrl[31].val[1] = 0; + state->Init_Ctrl[31].addr[2] = 166; + state->Init_Ctrl[31].bit[2] = 5; + state->Init_Ctrl[31].val[2] = 1; + + state->Init_Ctrl[32].Ctrl_Num = RFA_RSSI_REFL ; + state->Init_Ctrl[32].size = 3 ; + state->Init_Ctrl[32].addr[0] = 167; + state->Init_Ctrl[32].bit[0] = 0; + state->Init_Ctrl[32].val[0] = 1; + state->Init_Ctrl[32].addr[1] = 167; + state->Init_Ctrl[32].bit[1] = 1; + state->Init_Ctrl[32].val[1] = 1; + state->Init_Ctrl[32].addr[2] = 167; + state->Init_Ctrl[32].bit[2] = 2; + state->Init_Ctrl[32].val[2] = 0; + + state->Init_Ctrl[33].Ctrl_Num = RFA_FLR ; + state->Init_Ctrl[33].size = 4 ; + state->Init_Ctrl[33].addr[0] = 168; + state->Init_Ctrl[33].bit[0] = 0; + state->Init_Ctrl[33].val[0] = 0; + state->Init_Ctrl[33].addr[1] = 168; + state->Init_Ctrl[33].bit[1] = 1; + state->Init_Ctrl[33].val[1] = 1; + state->Init_Ctrl[33].addr[2] = 168; + state->Init_Ctrl[33].bit[2] = 2; + state->Init_Ctrl[33].val[2] = 0; + state->Init_Ctrl[33].addr[3] = 168; + state->Init_Ctrl[33].bit[3] = 3; + state->Init_Ctrl[33].val[3] = 0; + + state->Init_Ctrl[34].Ctrl_Num = RFA_CEIL ; + state->Init_Ctrl[34].size = 4 ; + state->Init_Ctrl[34].addr[0] = 168; + state->Init_Ctrl[34].bit[0] = 4; + state->Init_Ctrl[34].val[0] = 1; + state->Init_Ctrl[34].addr[1] = 168; + state->Init_Ctrl[34].bit[1] = 5; + state->Init_Ctrl[34].val[1] = 1; + state->Init_Ctrl[34].addr[2] = 168; + state->Init_Ctrl[34].bit[2] = 6; + state->Init_Ctrl[34].val[2] = 1; + state->Init_Ctrl[34].addr[3] = 168; + state->Init_Ctrl[34].bit[3] = 7; + state->Init_Ctrl[34].val[3] = 1; + + state->Init_Ctrl[35].Ctrl_Num = SEQ_EXTIQFSMPULSE ; + state->Init_Ctrl[35].size = 1 ; + state->Init_Ctrl[35].addr[0] = 135; + state->Init_Ctrl[35].bit[0] = 0; + state->Init_Ctrl[35].val[0] = 0; + + state->Init_Ctrl[36].Ctrl_Num = OVERRIDE_1 ; + state->Init_Ctrl[36].size = 1 ; + state->Init_Ctrl[36].addr[0] = 56; + state->Init_Ctrl[36].bit[0] = 3; + state->Init_Ctrl[36].val[0] = 0; + + state->Init_Ctrl[37].Ctrl_Num = BB_INITSTATE_DLPF_TUNE ; + state->Init_Ctrl[37].size = 7 ; + state->Init_Ctrl[37].addr[0] = 59; + state->Init_Ctrl[37].bit[0] = 1; + state->Init_Ctrl[37].val[0] = 0; + state->Init_Ctrl[37].addr[1] = 59; + state->Init_Ctrl[37].bit[1] = 2; + state->Init_Ctrl[37].val[1] = 0; + state->Init_Ctrl[37].addr[2] = 59; + state->Init_Ctrl[37].bit[2] = 3; + state->Init_Ctrl[37].val[2] = 0; + state->Init_Ctrl[37].addr[3] = 59; + state->Init_Ctrl[37].bit[3] = 4; + state->Init_Ctrl[37].val[3] = 0; + state->Init_Ctrl[37].addr[4] = 59; + state->Init_Ctrl[37].bit[4] = 5; + state->Init_Ctrl[37].val[4] = 0; + state->Init_Ctrl[37].addr[5] = 59; + state->Init_Ctrl[37].bit[5] = 6; + state->Init_Ctrl[37].val[5] = 0; + state->Init_Ctrl[37].addr[6] = 59; + state->Init_Ctrl[37].bit[6] = 7; + state->Init_Ctrl[37].val[6] = 0; + + state->Init_Ctrl[38].Ctrl_Num = TG_R_DIV ; + state->Init_Ctrl[38].size = 6 ; + state->Init_Ctrl[38].addr[0] = 32; + state->Init_Ctrl[38].bit[0] = 2; + state->Init_Ctrl[38].val[0] = 0; + state->Init_Ctrl[38].addr[1] = 32; + state->Init_Ctrl[38].bit[1] = 3; + state->Init_Ctrl[38].val[1] = 0; + state->Init_Ctrl[38].addr[2] = 32; + state->Init_Ctrl[38].bit[2] = 4; + state->Init_Ctrl[38].val[2] = 0; + state->Init_Ctrl[38].addr[3] = 32; + state->Init_Ctrl[38].bit[3] = 5; + state->Init_Ctrl[38].val[3] = 0; + state->Init_Ctrl[38].addr[4] = 32; + state->Init_Ctrl[38].bit[4] = 6; + state->Init_Ctrl[38].val[4] = 1; + state->Init_Ctrl[38].addr[5] = 32; + state->Init_Ctrl[38].bit[5] = 7; + state->Init_Ctrl[38].val[5] = 0; + + state->Init_Ctrl[39].Ctrl_Num = EN_CHP_LIN_B ; + state->Init_Ctrl[39].size = 1 ; + state->Init_Ctrl[39].addr[0] = 25; + state->Init_Ctrl[39].bit[0] = 3; + state->Init_Ctrl[39].val[0] = 1; + + + state->CH_Ctrl_Num = CHCTRL_NUM ; + + state->CH_Ctrl[0].Ctrl_Num = DN_POLY ; + state->CH_Ctrl[0].size = 2 ; + state->CH_Ctrl[0].addr[0] = 68; + state->CH_Ctrl[0].bit[0] = 6; + state->CH_Ctrl[0].val[0] = 1; + state->CH_Ctrl[0].addr[1] = 68; + state->CH_Ctrl[0].bit[1] = 7; + state->CH_Ctrl[0].val[1] = 1; + + state->CH_Ctrl[1].Ctrl_Num = DN_RFGAIN ; + state->CH_Ctrl[1].size = 2 ; + state->CH_Ctrl[1].addr[0] = 70; + state->CH_Ctrl[1].bit[0] = 6; + state->CH_Ctrl[1].val[0] = 1; + state->CH_Ctrl[1].addr[1] = 70; + state->CH_Ctrl[1].bit[1] = 7; + state->CH_Ctrl[1].val[1] = 0; + + state->CH_Ctrl[2].Ctrl_Num = DN_CAP_RFLPF ; + state->CH_Ctrl[2].size = 9 ; + state->CH_Ctrl[2].addr[0] = 69; + state->CH_Ctrl[2].bit[0] = 5; + state->CH_Ctrl[2].val[0] = 0; + state->CH_Ctrl[2].addr[1] = 69; + state->CH_Ctrl[2].bit[1] = 6; + state->CH_Ctrl[2].val[1] = 0; + state->CH_Ctrl[2].addr[2] = 69; + state->CH_Ctrl[2].bit[2] = 7; + state->CH_Ctrl[2].val[2] = 0; + state->CH_Ctrl[2].addr[3] = 68; + state->CH_Ctrl[2].bit[3] = 0; + state->CH_Ctrl[2].val[3] = 0; + state->CH_Ctrl[2].addr[4] = 68; + state->CH_Ctrl[2].bit[4] = 1; + state->CH_Ctrl[2].val[4] = 0; + state->CH_Ctrl[2].addr[5] = 68; + state->CH_Ctrl[2].bit[5] = 2; + state->CH_Ctrl[2].val[5] = 0; + state->CH_Ctrl[2].addr[6] = 68; + state->CH_Ctrl[2].bit[6] = 3; + state->CH_Ctrl[2].val[6] = 0; + state->CH_Ctrl[2].addr[7] = 68; + state->CH_Ctrl[2].bit[7] = 4; + state->CH_Ctrl[2].val[7] = 0; + state->CH_Ctrl[2].addr[8] = 68; + state->CH_Ctrl[2].bit[8] = 5; + state->CH_Ctrl[2].val[8] = 0; + + state->CH_Ctrl[3].Ctrl_Num = DN_EN_VHFUHFBAR ; + state->CH_Ctrl[3].size = 1 ; + state->CH_Ctrl[3].addr[0] = 70; + state->CH_Ctrl[3].bit[0] = 5; + state->CH_Ctrl[3].val[0] = 0; + + state->CH_Ctrl[4].Ctrl_Num = DN_GAIN_ADJUST ; + state->CH_Ctrl[4].size = 3 ; + state->CH_Ctrl[4].addr[0] = 73; + state->CH_Ctrl[4].bit[0] = 4; + state->CH_Ctrl[4].val[0] = 0; + state->CH_Ctrl[4].addr[1] = 73; + state->CH_Ctrl[4].bit[1] = 5; + state->CH_Ctrl[4].val[1] = 1; + state->CH_Ctrl[4].addr[2] = 73; + state->CH_Ctrl[4].bit[2] = 6; + state->CH_Ctrl[4].val[2] = 0; + + state->CH_Ctrl[5].Ctrl_Num = DN_IQTNBUF_AMP ; + state->CH_Ctrl[5].size = 4 ; + state->CH_Ctrl[5].addr[0] = 70; + state->CH_Ctrl[5].bit[0] = 0; + state->CH_Ctrl[5].val[0] = 0; + state->CH_Ctrl[5].addr[1] = 70; + state->CH_Ctrl[5].bit[1] = 1; + state->CH_Ctrl[5].val[1] = 0; + state->CH_Ctrl[5].addr[2] = 70; + state->CH_Ctrl[5].bit[2] = 2; + state->CH_Ctrl[5].val[2] = 0; + state->CH_Ctrl[5].addr[3] = 70; + state->CH_Ctrl[5].bit[3] = 3; + state->CH_Ctrl[5].val[3] = 0; + + state->CH_Ctrl[6].Ctrl_Num = DN_IQTNGNBFBIAS_BST ; + state->CH_Ctrl[6].size = 1 ; + state->CH_Ctrl[6].addr[0] = 70; + state->CH_Ctrl[6].bit[0] = 4; + state->CH_Ctrl[6].val[0] = 1; + + state->CH_Ctrl[7].Ctrl_Num = RFSYN_EN_OUTMUX ; + state->CH_Ctrl[7].size = 1 ; + state->CH_Ctrl[7].addr[0] = 111; + state->CH_Ctrl[7].bit[0] = 4; + state->CH_Ctrl[7].val[0] = 0; + + state->CH_Ctrl[8].Ctrl_Num = RFSYN_SEL_VCO_OUT ; + state->CH_Ctrl[8].size = 1 ; + state->CH_Ctrl[8].addr[0] = 111; + state->CH_Ctrl[8].bit[0] = 7; + state->CH_Ctrl[8].val[0] = 1; + + state->CH_Ctrl[9].Ctrl_Num = RFSYN_SEL_VCO_HI ; + state->CH_Ctrl[9].size = 1 ; + state->CH_Ctrl[9].addr[0] = 111; + state->CH_Ctrl[9].bit[0] = 6; + state->CH_Ctrl[9].val[0] = 1; + + state->CH_Ctrl[10].Ctrl_Num = RFSYN_SEL_DIVM ; + state->CH_Ctrl[10].size = 1 ; + state->CH_Ctrl[10].addr[0] = 111; + state->CH_Ctrl[10].bit[0] = 5; + state->CH_Ctrl[10].val[0] = 0; + + state->CH_Ctrl[11].Ctrl_Num = RFSYN_RF_DIV_BIAS ; + state->CH_Ctrl[11].size = 2 ; + state->CH_Ctrl[11].addr[0] = 110; + state->CH_Ctrl[11].bit[0] = 0; + state->CH_Ctrl[11].val[0] = 1; + state->CH_Ctrl[11].addr[1] = 110; + state->CH_Ctrl[11].bit[1] = 1; + state->CH_Ctrl[11].val[1] = 0; + + state->CH_Ctrl[12].Ctrl_Num = DN_SEL_FREQ ; + state->CH_Ctrl[12].size = 3 ; + state->CH_Ctrl[12].addr[0] = 69; + state->CH_Ctrl[12].bit[0] = 2; + state->CH_Ctrl[12].val[0] = 0; + state->CH_Ctrl[12].addr[1] = 69; + state->CH_Ctrl[12].bit[1] = 3; + state->CH_Ctrl[12].val[1] = 0; + state->CH_Ctrl[12].addr[2] = 69; + state->CH_Ctrl[12].bit[2] = 4; + state->CH_Ctrl[12].val[2] = 0; + + state->CH_Ctrl[13].Ctrl_Num = RFSYN_VCO_BIAS ; + state->CH_Ctrl[13].size = 6 ; + state->CH_Ctrl[13].addr[0] = 110; + state->CH_Ctrl[13].bit[0] = 2; + state->CH_Ctrl[13].val[0] = 0; + state->CH_Ctrl[13].addr[1] = 110; + state->CH_Ctrl[13].bit[1] = 3; + state->CH_Ctrl[13].val[1] = 0; + state->CH_Ctrl[13].addr[2] = 110; + state->CH_Ctrl[13].bit[2] = 4; + state->CH_Ctrl[13].val[2] = 0; + state->CH_Ctrl[13].addr[3] = 110; + state->CH_Ctrl[13].bit[3] = 5; + state->CH_Ctrl[13].val[3] = 0; + state->CH_Ctrl[13].addr[4] = 110; + state->CH_Ctrl[13].bit[4] = 6; + state->CH_Ctrl[13].val[4] = 0; + state->CH_Ctrl[13].addr[5] = 110; + state->CH_Ctrl[13].bit[5] = 7; + state->CH_Ctrl[13].val[5] = 1; + + state->CH_Ctrl[14].Ctrl_Num = CHCAL_INT_MOD_RF ; + state->CH_Ctrl[14].size = 7 ; + state->CH_Ctrl[14].addr[0] = 14; + state->CH_Ctrl[14].bit[0] = 0; + state->CH_Ctrl[14].val[0] = 0; + state->CH_Ctrl[14].addr[1] = 14; + state->CH_Ctrl[14].bit[1] = 1; + state->CH_Ctrl[14].val[1] = 0; + state->CH_Ctrl[14].addr[2] = 14; + state->CH_Ctrl[14].bit[2] = 2; + state->CH_Ctrl[14].val[2] = 0; + state->CH_Ctrl[14].addr[3] = 14; + state->CH_Ctrl[14].bit[3] = 3; + state->CH_Ctrl[14].val[3] = 0; + state->CH_Ctrl[14].addr[4] = 14; + state->CH_Ctrl[14].bit[4] = 4; + state->CH_Ctrl[14].val[4] = 0; + state->CH_Ctrl[14].addr[5] = 14; + state->CH_Ctrl[14].bit[5] = 5; + state->CH_Ctrl[14].val[5] = 0; + state->CH_Ctrl[14].addr[6] = 14; + state->CH_Ctrl[14].bit[6] = 6; + state->CH_Ctrl[14].val[6] = 0; + + state->CH_Ctrl[15].Ctrl_Num = CHCAL_FRAC_MOD_RF ; + state->CH_Ctrl[15].size = 18 ; + state->CH_Ctrl[15].addr[0] = 17; + state->CH_Ctrl[15].bit[0] = 6; + state->CH_Ctrl[15].val[0] = 0; + state->CH_Ctrl[15].addr[1] = 17; + state->CH_Ctrl[15].bit[1] = 7; + state->CH_Ctrl[15].val[1] = 0; + state->CH_Ctrl[15].addr[2] = 16; + state->CH_Ctrl[15].bit[2] = 0; + state->CH_Ctrl[15].val[2] = 0; + state->CH_Ctrl[15].addr[3] = 16; + state->CH_Ctrl[15].bit[3] = 1; + state->CH_Ctrl[15].val[3] = 0; + state->CH_Ctrl[15].addr[4] = 16; + state->CH_Ctrl[15].bit[4] = 2; + state->CH_Ctrl[15].val[4] = 0; + state->CH_Ctrl[15].addr[5] = 16; + state->CH_Ctrl[15].bit[5] = 3; + state->CH_Ctrl[15].val[5] = 0; + state->CH_Ctrl[15].addr[6] = 16; + state->CH_Ctrl[15].bit[6] = 4; + state->CH_Ctrl[15].val[6] = 0; + state->CH_Ctrl[15].addr[7] = 16; + state->CH_Ctrl[15].bit[7] = 5; + state->CH_Ctrl[15].val[7] = 0; + state->CH_Ctrl[15].addr[8] = 16; + state->CH_Ctrl[15].bit[8] = 6; + state->CH_Ctrl[15].val[8] = 0; + state->CH_Ctrl[15].addr[9] = 16; + state->CH_Ctrl[15].bit[9] = 7; + state->CH_Ctrl[15].val[9] = 0; + state->CH_Ctrl[15].addr[10] = 15; + state->CH_Ctrl[15].bit[10] = 0; + state->CH_Ctrl[15].val[10] = 0; + state->CH_Ctrl[15].addr[11] = 15; + state->CH_Ctrl[15].bit[11] = 1; + state->CH_Ctrl[15].val[11] = 0; + state->CH_Ctrl[15].addr[12] = 15; + state->CH_Ctrl[15].bit[12] = 2; + state->CH_Ctrl[15].val[12] = 0; + state->CH_Ctrl[15].addr[13] = 15; + state->CH_Ctrl[15].bit[13] = 3; + state->CH_Ctrl[15].val[13] = 0; + state->CH_Ctrl[15].addr[14] = 15; + state->CH_Ctrl[15].bit[14] = 4; + state->CH_Ctrl[15].val[14] = 0; + state->CH_Ctrl[15].addr[15] = 15; + state->CH_Ctrl[15].bit[15] = 5; + state->CH_Ctrl[15].val[15] = 0; + state->CH_Ctrl[15].addr[16] = 15; + state->CH_Ctrl[15].bit[16] = 6; + state->CH_Ctrl[15].val[16] = 1; + state->CH_Ctrl[15].addr[17] = 15; + state->CH_Ctrl[15].bit[17] = 7; + state->CH_Ctrl[15].val[17] = 1; + + state->CH_Ctrl[16].Ctrl_Num = RFSYN_LPF_R ; + state->CH_Ctrl[16].size = 5 ; + state->CH_Ctrl[16].addr[0] = 112; + state->CH_Ctrl[16].bit[0] = 0; + state->CH_Ctrl[16].val[0] = 0; + state->CH_Ctrl[16].addr[1] = 112; + state->CH_Ctrl[16].bit[1] = 1; + state->CH_Ctrl[16].val[1] = 0; + state->CH_Ctrl[16].addr[2] = 112; + state->CH_Ctrl[16].bit[2] = 2; + state->CH_Ctrl[16].val[2] = 0; + state->CH_Ctrl[16].addr[3] = 112; + state->CH_Ctrl[16].bit[3] = 3; + state->CH_Ctrl[16].val[3] = 0; + state->CH_Ctrl[16].addr[4] = 112; + state->CH_Ctrl[16].bit[4] = 4; + state->CH_Ctrl[16].val[4] = 1; + + state->CH_Ctrl[17].Ctrl_Num = CHCAL_EN_INT_RF ; + state->CH_Ctrl[17].size = 1 ; + state->CH_Ctrl[17].addr[0] = 14; + state->CH_Ctrl[17].bit[0] = 7; + state->CH_Ctrl[17].val[0] = 0; + + state->CH_Ctrl[18].Ctrl_Num = TG_LO_DIVVAL ; + state->CH_Ctrl[18].size = 4 ; + state->CH_Ctrl[18].addr[0] = 107; + state->CH_Ctrl[18].bit[0] = 3; + state->CH_Ctrl[18].val[0] = 0; + state->CH_Ctrl[18].addr[1] = 107; + state->CH_Ctrl[18].bit[1] = 4; + state->CH_Ctrl[18].val[1] = 0; + state->CH_Ctrl[18].addr[2] = 107; + state->CH_Ctrl[18].bit[2] = 5; + state->CH_Ctrl[18].val[2] = 0; + state->CH_Ctrl[18].addr[3] = 107; + state->CH_Ctrl[18].bit[3] = 6; + state->CH_Ctrl[18].val[3] = 0; + + state->CH_Ctrl[19].Ctrl_Num = TG_LO_SELVAL ; + state->CH_Ctrl[19].size = 3 ; + state->CH_Ctrl[19].addr[0] = 107; + state->CH_Ctrl[19].bit[0] = 7; + state->CH_Ctrl[19].val[0] = 1; + state->CH_Ctrl[19].addr[1] = 106; + state->CH_Ctrl[19].bit[1] = 0; + state->CH_Ctrl[19].val[1] = 1; + state->CH_Ctrl[19].addr[2] = 106; + state->CH_Ctrl[19].bit[2] = 1; + state->CH_Ctrl[19].val[2] = 1; + + state->CH_Ctrl[20].Ctrl_Num = TG_DIV_VAL ; + state->CH_Ctrl[20].size = 11 ; + state->CH_Ctrl[20].addr[0] = 109; + state->CH_Ctrl[20].bit[0] = 2; + state->CH_Ctrl[20].val[0] = 0; + state->CH_Ctrl[20].addr[1] = 109; + state->CH_Ctrl[20].bit[1] = 3; + state->CH_Ctrl[20].val[1] = 0; + state->CH_Ctrl[20].addr[2] = 109; + state->CH_Ctrl[20].bit[2] = 4; + state->CH_Ctrl[20].val[2] = 0; + state->CH_Ctrl[20].addr[3] = 109; + state->CH_Ctrl[20].bit[3] = 5; + state->CH_Ctrl[20].val[3] = 0; + state->CH_Ctrl[20].addr[4] = 109; + state->CH_Ctrl[20].bit[4] = 6; + state->CH_Ctrl[20].val[4] = 0; + state->CH_Ctrl[20].addr[5] = 109; + state->CH_Ctrl[20].bit[5] = 7; + state->CH_Ctrl[20].val[5] = 0; + state->CH_Ctrl[20].addr[6] = 108; + state->CH_Ctrl[20].bit[6] = 0; + state->CH_Ctrl[20].val[6] = 0; + state->CH_Ctrl[20].addr[7] = 108; + state->CH_Ctrl[20].bit[7] = 1; + state->CH_Ctrl[20].val[7] = 0; + state->CH_Ctrl[20].addr[8] = 108; + state->CH_Ctrl[20].bit[8] = 2; + state->CH_Ctrl[20].val[8] = 1; + state->CH_Ctrl[20].addr[9] = 108; + state->CH_Ctrl[20].bit[9] = 3; + state->CH_Ctrl[20].val[9] = 1; + state->CH_Ctrl[20].addr[10] = 108; + state->CH_Ctrl[20].bit[10] = 4; + state->CH_Ctrl[20].val[10] = 1; + + state->CH_Ctrl[21].Ctrl_Num = TG_VCO_BIAS ; + state->CH_Ctrl[21].size = 6 ; + state->CH_Ctrl[21].addr[0] = 106; + state->CH_Ctrl[21].bit[0] = 2; + state->CH_Ctrl[21].val[0] = 0; + state->CH_Ctrl[21].addr[1] = 106; + state->CH_Ctrl[21].bit[1] = 3; + state->CH_Ctrl[21].val[1] = 0; + state->CH_Ctrl[21].addr[2] = 106; + state->CH_Ctrl[21].bit[2] = 4; + state->CH_Ctrl[21].val[2] = 0; + state->CH_Ctrl[21].addr[3] = 106; + state->CH_Ctrl[21].bit[3] = 5; + state->CH_Ctrl[21].val[3] = 0; + state->CH_Ctrl[21].addr[4] = 106; + state->CH_Ctrl[21].bit[4] = 6; + state->CH_Ctrl[21].val[4] = 0; + state->CH_Ctrl[21].addr[5] = 106; + state->CH_Ctrl[21].bit[5] = 7; + state->CH_Ctrl[21].val[5] = 1; + + state->CH_Ctrl[22].Ctrl_Num = SEQ_EXTPOWERUP ; + state->CH_Ctrl[22].size = 1 ; + state->CH_Ctrl[22].addr[0] = 138; + state->CH_Ctrl[22].bit[0] = 4; + state->CH_Ctrl[22].val[0] = 1; + + state->CH_Ctrl[23].Ctrl_Num = OVERRIDE_2 ; + state->CH_Ctrl[23].size = 1 ; + state->CH_Ctrl[23].addr[0] = 17; + state->CH_Ctrl[23].bit[0] = 5; + state->CH_Ctrl[23].val[0] = 0; + + state->CH_Ctrl[24].Ctrl_Num = OVERRIDE_3 ; + state->CH_Ctrl[24].size = 1 ; + state->CH_Ctrl[24].addr[0] = 111; + state->CH_Ctrl[24].bit[0] = 3; + state->CH_Ctrl[24].val[0] = 0; + + state->CH_Ctrl[25].Ctrl_Num = OVERRIDE_4 ; + state->CH_Ctrl[25].size = 1 ; + state->CH_Ctrl[25].addr[0] = 112; + state->CH_Ctrl[25].bit[0] = 7; + state->CH_Ctrl[25].val[0] = 0; + + state->CH_Ctrl[26].Ctrl_Num = SEQ_FSM_PULSE ; + state->CH_Ctrl[26].size = 1 ; + state->CH_Ctrl[26].addr[0] = 136; + state->CH_Ctrl[26].bit[0] = 7; + state->CH_Ctrl[26].val[0] = 0; + + state->CH_Ctrl[27].Ctrl_Num = GPIO_4B ; + state->CH_Ctrl[27].size = 1 ; + state->CH_Ctrl[27].addr[0] = 149; + state->CH_Ctrl[27].bit[0] = 7; + state->CH_Ctrl[27].val[0] = 0; + + state->CH_Ctrl[28].Ctrl_Num = GPIO_3B ; + state->CH_Ctrl[28].size = 1 ; + state->CH_Ctrl[28].addr[0] = 149; + state->CH_Ctrl[28].bit[0] = 6; + state->CH_Ctrl[28].val[0] = 0; + + state->CH_Ctrl[29].Ctrl_Num = GPIO_4 ; + state->CH_Ctrl[29].size = 1 ; + state->CH_Ctrl[29].addr[0] = 149; + state->CH_Ctrl[29].bit[0] = 5; + state->CH_Ctrl[29].val[0] = 1; + + state->CH_Ctrl[30].Ctrl_Num = GPIO_3 ; + state->CH_Ctrl[30].size = 1 ; + state->CH_Ctrl[30].addr[0] = 149; + state->CH_Ctrl[30].bit[0] = 4; + state->CH_Ctrl[30].val[0] = 1; + + state->CH_Ctrl[31].Ctrl_Num = GPIO_1B ; + state->CH_Ctrl[31].size = 1 ; + state->CH_Ctrl[31].addr[0] = 149; + state->CH_Ctrl[31].bit[0] = 3; + state->CH_Ctrl[31].val[0] = 0; + + state->CH_Ctrl[32].Ctrl_Num = DAC_A_ENABLE ; + state->CH_Ctrl[32].size = 1 ; + state->CH_Ctrl[32].addr[0] = 93; + state->CH_Ctrl[32].bit[0] = 1; + state->CH_Ctrl[32].val[0] = 0; + + state->CH_Ctrl[33].Ctrl_Num = DAC_B_ENABLE ; + state->CH_Ctrl[33].size = 1 ; + state->CH_Ctrl[33].addr[0] = 93; + state->CH_Ctrl[33].bit[0] = 0; + state->CH_Ctrl[33].val[0] = 0; + + state->CH_Ctrl[34].Ctrl_Num = DAC_DIN_A ; + state->CH_Ctrl[34].size = 6 ; + state->CH_Ctrl[34].addr[0] = 92; + state->CH_Ctrl[34].bit[0] = 2; + state->CH_Ctrl[34].val[0] = 0; + state->CH_Ctrl[34].addr[1] = 92; + state->CH_Ctrl[34].bit[1] = 3; + state->CH_Ctrl[34].val[1] = 0; + state->CH_Ctrl[34].addr[2] = 92; + state->CH_Ctrl[34].bit[2] = 4; + state->CH_Ctrl[34].val[2] = 0; + state->CH_Ctrl[34].addr[3] = 92; + state->CH_Ctrl[34].bit[3] = 5; + state->CH_Ctrl[34].val[3] = 0; + state->CH_Ctrl[34].addr[4] = 92; + state->CH_Ctrl[34].bit[4] = 6; + state->CH_Ctrl[34].val[4] = 0; + state->CH_Ctrl[34].addr[5] = 92; + state->CH_Ctrl[34].bit[5] = 7; + state->CH_Ctrl[34].val[5] = 0; + + state->CH_Ctrl[35].Ctrl_Num = DAC_DIN_B ; + state->CH_Ctrl[35].size = 6 ; + state->CH_Ctrl[35].addr[0] = 93; + state->CH_Ctrl[35].bit[0] = 2; + state->CH_Ctrl[35].val[0] = 0; + state->CH_Ctrl[35].addr[1] = 93; + state->CH_Ctrl[35].bit[1] = 3; + state->CH_Ctrl[35].val[1] = 0; + state->CH_Ctrl[35].addr[2] = 93; + state->CH_Ctrl[35].bit[2] = 4; + state->CH_Ctrl[35].val[2] = 0; + state->CH_Ctrl[35].addr[3] = 93; + state->CH_Ctrl[35].bit[3] = 5; + state->CH_Ctrl[35].val[3] = 0; + state->CH_Ctrl[35].addr[4] = 93; + state->CH_Ctrl[35].bit[4] = 6; + state->CH_Ctrl[35].val[4] = 0; + state->CH_Ctrl[35].addr[5] = 93; + state->CH_Ctrl[35].bit[5] = 7; + state->CH_Ctrl[35].val[5] = 0; #ifdef _MXL_PRODUCTION - Tuner->CH_Ctrl[36].Ctrl_Num = RFSYN_EN_DIV ; - Tuner->CH_Ctrl[36].size = 1 ; - Tuner->CH_Ctrl[36].addr[0] = 109; - Tuner->CH_Ctrl[36].bit[0] = 1; - Tuner->CH_Ctrl[36].val[0] = 1; - - Tuner->CH_Ctrl[37].Ctrl_Num = RFSYN_DIVM ; - Tuner->CH_Ctrl[37].size = 2 ; - Tuner->CH_Ctrl[37].addr[0] = 112; - Tuner->CH_Ctrl[37].bit[0] = 5; - Tuner->CH_Ctrl[37].val[0] = 0; - Tuner->CH_Ctrl[37].addr[1] = 112; - Tuner->CH_Ctrl[37].bit[1] = 6; - Tuner->CH_Ctrl[37].val[1] = 0; - - Tuner->CH_Ctrl[38].Ctrl_Num = DN_BYPASS_AGC_I2C ; - Tuner->CH_Ctrl[38].size = 1 ; - Tuner->CH_Ctrl[38].addr[0] = 65; - Tuner->CH_Ctrl[38].bit[0] = 1; - Tuner->CH_Ctrl[38].val[0] = 0; + state->CH_Ctrl[36].Ctrl_Num = RFSYN_EN_DIV ; + state->CH_Ctrl[36].size = 1 ; + state->CH_Ctrl[36].addr[0] = 109; + state->CH_Ctrl[36].bit[0] = 1; + state->CH_Ctrl[36].val[0] = 1; + + state->CH_Ctrl[37].Ctrl_Num = RFSYN_DIVM ; + state->CH_Ctrl[37].size = 2 ; + state->CH_Ctrl[37].addr[0] = 112; + state->CH_Ctrl[37].bit[0] = 5; + state->CH_Ctrl[37].val[0] = 0; + state->CH_Ctrl[37].addr[1] = 112; + state->CH_Ctrl[37].bit[1] = 6; + state->CH_Ctrl[37].val[1] = 0; + + state->CH_Ctrl[38].Ctrl_Num = DN_BYPASS_AGC_I2C ; + state->CH_Ctrl[38].size = 1 ; + state->CH_Ctrl[38].addr[0] = 65; + state->CH_Ctrl[38].bit[0] = 1; + state->CH_Ctrl[38].val[0] = 0; #endif return 0 ; @@ -1832,13 +1681,14 @@ u16 MXL5005_ControlInit(Tuner_struct *Tuner) // MaxLinear source code - MXL5005_c.cpp // MXL5005.cpp : Defines the initialization routines for the DLL. // 2.6.12 - -void InitTunerControls(Tuner_struct *Tuner) +// DONE +void InitTunerControls(struct dvb_frontend *fe) { - MXL5005_RegisterInit(Tuner) ; - MXL5005_ControlInit(Tuner) ; + struct mxl5005s_state *state = fe->demodulator_priv; + MXL5005_RegisterInit(fe); + MXL5005_ControlInit(fe); #ifdef _MXL_INTERNAL - MXL5005_MXLControlInit(Tuner) ; + MXL5005_MXLControlInit(fe); #endif } @@ -1857,15 +1707,15 @@ void InitTunerControls(Tuner_struct *Tuner) // Tuner_struct: structure defined at higher level // // Mode: Tuner Mode (Analog/Digital) // // IF_Mode: IF Mode ( Zero/Low ) // -// Bandwidth: Filter Channel Bandwidth (in Hz) // +// Bandwidth: Filter Channel Bandwidth (in Hz) // // IF_out: Desired IF out Frequency (in Hz) // // Fxtal: Crystal Frerquency (in Hz) // -// TOP: 0: Dual AGC; Value: take over point // -// IF_OUT_LOAD: IF out load resistor (200/300 Ohms) // -// CLOCK_OUT: 0: Turn off clock out; 1: turn on clock out // -// DIV_OUT: 0: Div-1; 1: Div-4 // -// CAPSELECT: 0: Disable On-chip pulling cap; 1: Enable // -// EN_RSSI: 0: Disable RSSI; 1: Enable RSSI // +// TOP: 0: Dual AGC; Value: take over point // +// IF_OUT_LOAD: IF out load resistor (200/300 Ohms) // +// CLOCK_OUT: 0: Turn off clock out; 1: turn on clock out // +// DIV_OUT: 0: Div-1; 1: Div-4 // +// CAPSELECT: 0: Disable On-chip pulling cap; 1: Enable // +// EN_RSSI: 0: Disable RSSI; 1: Enable RSSI // // // // Outputs: // // Tuner // @@ -1875,49 +1725,51 @@ void InitTunerControls(Tuner_struct *Tuner) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -u16 MXL5005_TunerConfig(Tuner_struct *Tuner, - u8 Mode, // 0: Analog Mode ; 1: Digital Mode - u8 IF_mode, // for Analog Mode, 0: zero IF; 1: low IF - u32 Bandwidth, // filter channel bandwidth (6, 7, 8) - u32 IF_out, // Desired IF Out Frequency - u32 Fxtal, // XTAL Frequency - u8 AGC_Mode, // AGC Mode - Dual AGC: 0, Single AGC: 1 - u16 TOP, // 0: Dual AGC; Value: take over point - u16 IF_OUT_LOAD, // IF Out Load Resistor (200 / 300 Ohms) - u8 CLOCK_OUT, // 0: turn off clock out; 1: turn on clock out - u8 DIV_OUT, // 0: Div-1; 1: Div-4 - u8 CAPSELECT, // 0: disable On-Chip pulling cap; 1: enable - u8 EN_RSSI, // 0: disable RSSI; 1: enable RSSI - u8 Mod_Type, // Modulation Type; - // 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable - u8 TF_Type // Tracking Filter - // 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H +// DONE +u16 MXL5005_TunerConfig(struct dvb_frontend *fe, + u8 Mode, /* 0: Analog Mode ; 1: Digital Mode */ + u8 IF_mode, /* for Analog Mode, 0: zero IF; 1: low IF */ + u32 Bandwidth, /* filter channel bandwidth (6, 7, 8) */ + u32 IF_out, /* Desired IF Out Frequency */ + u32 Fxtal, /* XTAL Frequency */ + u8 AGC_Mode, /* AGC Mode - Dual AGC: 0, Single AGC: 1 */ + u16 TOP, /* 0: Dual AGC; Value: take over point */ + u16 IF_OUT_LOAD, /* IF Out Load Resistor (200 / 300 Ohms) */ + u8 CLOCK_OUT, /* 0: turn off clock out; 1: turn on clock out */ + u8 DIV_OUT, /* 0: Div-1; 1: Div-4 */ + u8 CAPSELECT, /* 0: disable On-Chip pulling cap; 1: enable */ + u8 EN_RSSI, /* 0: disable RSSI; 1: enable RSSI */ + u8 Mod_Type, /* Modulation Type; */ + /* 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable */ + u8 TF_Type /* Tracking Filter */ + /* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */ ) { - u16 status = 0 ; + struct mxl5005s_state *state = fe->demodulator_priv; + u16 status = 0; - Tuner->Mode = Mode ; - Tuner->IF_Mode = IF_mode ; - Tuner->Chan_Bandwidth = Bandwidth ; - Tuner->IF_OUT = IF_out ; - Tuner->Fxtal = Fxtal ; - Tuner->AGC_Mode = AGC_Mode ; - Tuner->TOP = TOP ; - Tuner->IF_OUT_LOAD = IF_OUT_LOAD ; - Tuner->CLOCK_OUT = CLOCK_OUT ; - Tuner->DIV_OUT = DIV_OUT ; - Tuner->CAPSELECT = CAPSELECT ; - Tuner->EN_RSSI = EN_RSSI ; - Tuner->Mod_Type = Mod_Type ; - Tuner->TF_Type = TF_Type ; + state->Mode = Mode; + state->IF_Mode = IF_mode; + state->Chan_Bandwidth = Bandwidth; + state->IF_OUT = IF_out; + state->Fxtal = Fxtal; + state->AGC_Mode = AGC_Mode; + state->TOP = TOP; + state->IF_OUT_LOAD = IF_OUT_LOAD; + state->CLOCK_OUT = CLOCK_OUT; + state->DIV_OUT = DIV_OUT; + state->CAPSELECT = CAPSELECT; + state->EN_RSSI = EN_RSSI; + state->Mod_Type = Mod_Type; + state->TF_Type = TF_Type; /* Initialize all the controls and registers */ - InitTunerControls (Tuner) ; + InitTunerControls(fe); /* Synthesizer LO frequency calculation */ - MXL_SynthIFLO_Calc( Tuner ) ; + MXL_SynthIFLO_Calc(fe); - return status ; + return status; } /////////////////////////////////////////////////////////////////////////////// @@ -1943,22 +1795,18 @@ u16 MXL5005_TunerConfig(Tuner_struct *Tuner, // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -void MXL_SynthIFLO_Calc(Tuner_struct *Tuner) +// DONE +void MXL_SynthIFLO_Calc(struct dvb_frontend *fe) { - if (Tuner->Mode == 1) // Digital Mode - { - Tuner->IF_LO = Tuner->IF_OUT ; - } - else // Analog Mode + struct mxl5005s_state *state = fe->demodulator_priv; + if (Tuner->Mode == 1) /* Digital Mode */ + state->IF_LO = state->IF_OUT; + else /* Analog Mode */ { - if(Tuner->IF_Mode == 0) // Analog Zero IF mode - { - Tuner->IF_LO = Tuner->IF_OUT + 400000 ; - } - else // Analog Low IF mode - { - Tuner->IF_LO = Tuner->IF_OUT + Tuner->Chan_Bandwidth/2 ; - } + if(state->IF_Mode == 0) /* Analog Zero IF mode */ + state->IF_LO = state->IF_OUT + 400000; + else /* Analog Low IF mode */ + state->IF_LO = state->IF_OUT + state->Chan_Bandwidth/2; } } @@ -1986,25 +1834,22 @@ void MXL_SynthIFLO_Calc(Tuner_struct *Tuner) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -void MXL_SynthRFTGLO_Calc(Tuner_struct *Tuner) +// DONE +void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe) { - if (Tuner->Mode == 1) // Digital Mode - { + struct mxl5005s_state *state = fe->demodulator_priv; + + if (state->Mode == 1) /* Digital Mode */ { //remove 20.48MHz setting for 2.6.10 - Tuner->RF_LO = Tuner->RF_IN ; - Tuner->TG_LO = Tuner->RF_IN - 750000 ; //change for 2.6.6 - } - else // Analog Mode - { - if(Tuner->IF_Mode == 0) // Analog Zero IF mode - { - Tuner->RF_LO = Tuner->RF_IN - 400000 ; - Tuner->TG_LO = Tuner->RF_IN - 1750000 ; - } - else // Analog Low IF mode - { - Tuner->RF_LO = Tuner->RF_IN - Tuner->Chan_Bandwidth/2 ; - Tuner->TG_LO = Tuner->RF_IN - Tuner->Chan_Bandwidth + 500000 ; + state->RF_LO = state->RF_IN; + state->TG_LO = state->RF_IN - 750000; //change for 2.6.6 + } else /* Analog Mode */ { + if(state->IF_Mode == 0) /* Analog Zero IF mode */ { + state->RF_LO = state->RF_IN - 400000; + state->TG_LO = state->RF_IN - 1750000; + } else /* Analog Low IF mode */ { + state->RF_LO = state->RF_IN - state->Chan_Bandwidth/2; + state->TG_LO = state->RF_IN - state->Chan_Bandwidth + 500000; } } } @@ -2028,16 +1873,18 @@ void MXL_SynthRFTGLO_Calc(Tuner_struct *Tuner) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -u16 MXL_OverwriteICDefault( Tuner_struct *Tuner) +// DONE +u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) { - u16 status = 0 ; + struct mxl5005s_state *state = fe->demodulator_priv; + u16 status = 0; - status += MXL_ControlWrite(Tuner, OVERRIDE_1, 1) ; - status += MXL_ControlWrite(Tuner, OVERRIDE_2, 1) ; - status += MXL_ControlWrite(Tuner, OVERRIDE_3, 1) ; - status += MXL_ControlWrite(Tuner, OVERRIDE_4, 1) ; + status += MXL_ControlWrite(fe, OVERRIDE_1, 1); + status += MXL_ControlWrite(fe, OVERRIDE_2, 1); + status += MXL_ControlWrite(fe, OVERRIDE_3, 1); + status += MXL_ControlWrite(fe, OVERRIDE_4, 1); - return status ; + return status; } /////////////////////////////////////////////////////////////////////////////// @@ -2065,363 +1912,338 @@ u16 MXL_OverwriteICDefault( Tuner_struct *Tuner) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -u16 MXL_BlockInit( Tuner_struct *Tuner ) +// DONE +u16 MXL_BlockInit(struct dvb_frontend *fe) { - u16 status = 0 ; + struct mxl5005s_state *state = fe->demodulator_priv; + u16 status = 0; - status += MXL_OverwriteICDefault(Tuner) ; + status += MXL_OverwriteICDefault(fe); - // - // Downconverter Control - // Dig Ana - status += MXL_ControlWrite(Tuner, DN_IQTN_AMP_CUT, Tuner->Mode ? 1 : 0) ; + /* Downconverter Control Dig Ana */ + status += MXL_ControlWrite(fe, DN_IQTN_AMP_CUT, state->Mode ? 1 : 0); - // - // Filter Control - // Dig Ana - status += MXL_ControlWrite(Tuner, BB_MODE, Tuner->Mode ? 0 : 1) ; - status += MXL_ControlWrite(Tuner, BB_BUF, Tuner->Mode ? 3 : 2) ; - status += MXL_ControlWrite(Tuner, BB_BUF_OA, Tuner->Mode ? 1 : 0) ; - - status += MXL_ControlWrite(Tuner, BB_IQSWAP, Tuner->Mode ? 0 : 1) ; - status += MXL_ControlWrite(Tuner, BB_INITSTATE_DLPF_TUNE, 0) ; - - // Initialize Low-Pass Filter - if (Tuner->Mode) { // Digital Mode - switch (Tuner->Chan_Bandwidth) { + /* Filter Control Dig Ana */ + status += MXL_ControlWrite(fe, BB_MODE, state->Mode ? 0 : 1); + status += MXL_ControlWrite(fe, BB_BUF, state->Mode ? 3 : 2); + status += MXL_ControlWrite(fe, BB_BUF_OA, state->Mode ? 1 : 0); + status += MXL_ControlWrite(fe, BB_IQSWAP, state->Mode ? 0 : 1); + status += MXL_ControlWrite(fe, BB_INITSTATE_DLPF_TUNE, 0); + + /* Initialize Low-Pass Filter */ + if (state->Mode) { /* Digital Mode */ + switch (state->Chan_Bandwidth) { case 8000000: - status += MXL_ControlWrite(Tuner, BB_DLPF_BANDSEL, 0) ; - break ; + status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 0); + break; case 7000000: - status += MXL_ControlWrite(Tuner, BB_DLPF_BANDSEL, 2) ; - break ; + status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 2); + break; case 6000000: - status += MXL_ControlWrite(Tuner, BB_DLPF_BANDSEL, 3) ; - break ; - } - } else { // Analog Mode - switch (Tuner->Chan_Bandwidth) { - case 8000000: // Low Zero - status += MXL_ControlWrite(Tuner, BB_ALPF_BANDSELECT, (Tuner->IF_Mode ? 0 : 3)) ; - break ; + status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 3); + break; + } + } else { /* Analog Mode */ + switch (state->Chan_Bandwidth) { + case 8000000: /* Low Zero */ + status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT, (state->IF_Mode ? 0 : 3)); + break; case 7000000: - status += MXL_ControlWrite(Tuner, BB_ALPF_BANDSELECT, (Tuner->IF_Mode ? 1 : 4)) ; - break ; + status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT, (state->IF_Mode ? 1 : 4)); + break; case 6000000: - status += MXL_ControlWrite(Tuner, BB_ALPF_BANDSELECT, (Tuner->IF_Mode ? 2 : 5)) ; - break ; + status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT, (state->IF_Mode ? 2 : 5)); + break; } } - // - // Charge Pump Control - // Dig Ana - status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, Tuner->Mode ? 5 : 8) ; - status += MXL_ControlWrite(Tuner, RFSYN_EN_CHP_HIGAIN, Tuner->Mode ? 1 : 1) ; - status += MXL_ControlWrite(Tuner, EN_CHP_LIN_B, Tuner->Mode ? 0 : 0) ; + /* Charge Pump Control Dig Ana */ + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, state->Mode ? 5 : 8); + status += MXL_ControlWrite(fe, RFSYN_EN_CHP_HIGAIN, state->Mode ? 1 : 1); + status += MXL_ControlWrite(fe, EN_CHP_LIN_B, state->Mode ? 0 : 0); - // - // AGC TOP Control - // - if (Tuner->AGC_Mode == 0) // Dual AGC - { - status += MXL_ControlWrite(Tuner, AGC_IF, 15) ; - status += MXL_ControlWrite(Tuner, AGC_RF, 15) ; + /* AGC TOP Control */ + if (state->AGC_Mode == 0) /* Dual AGC */ { + status += MXL_ControlWrite(fe, AGC_IF, 15); + status += MXL_ControlWrite(fe, AGC_RF, 15); } - else // Single AGC Mode Dig Ana - status += MXL_ControlWrite(Tuner, AGC_RF, Tuner->Mode? 15 : 12) ; + else /* Single AGC Mode Dig Ana */ + status += MXL_ControlWrite(fe, AGC_RF, state->Mode ? 15 : 12); - if (Tuner->TOP == 55) // TOP == 5.5 - status += MXL_ControlWrite(Tuner, AGC_IF, 0x0) ; + if (state->TOP == 55) /* TOP == 5.5 */ + status += MXL_ControlWrite(fe, AGC_IF, 0x0); - if (Tuner->TOP == 72) // TOP == 7.2 - status += MXL_ControlWrite(Tuner, AGC_IF, 0x1) ; + if (state->TOP == 72) /* TOP == 7.2 */ + status += MXL_ControlWrite(fe, AGC_IF, 0x1); - if (Tuner->TOP == 92) // TOP == 9.2 - status += MXL_ControlWrite(Tuner, AGC_IF, 0x2) ; + if (state->TOP == 92) /* TOP == 9.2 */ + status += MXL_ControlWrite(fe, AGC_IF, 0x2); - if (Tuner->TOP == 110) // TOP == 11.0 - status += MXL_ControlWrite(Tuner, AGC_IF, 0x3) ; + if (state->TOP == 110) /* TOP == 11.0 */ + status += MXL_ControlWrite(fe, AGC_IF, 0x3); - if (Tuner->TOP == 129) // TOP == 12.9 - status += MXL_ControlWrite(Tuner, AGC_IF, 0x4) ; + if (state->TOP == 129) /* TOP == 12.9 */ + status += MXL_ControlWrite(fe, AGC_IF, 0x4); - if (Tuner->TOP == 147) // TOP == 14.7 - status += MXL_ControlWrite(Tuner, AGC_IF, 0x5) ; + if (state->TOP == 147) /* TOP == 14.7 */ + status += MXL_ControlWrite(fe, AGC_IF, 0x5); - if (Tuner->TOP == 168) // TOP == 16.8 - status += MXL_ControlWrite(Tuner, AGC_IF, 0x6) ; + if (state->TOP == 168) /* TOP == 16.8 */ + status += MXL_ControlWrite(fe, AGC_IF, 0x6); - if (Tuner->TOP == 194) // TOP == 19.4 - status += MXL_ControlWrite(Tuner, AGC_IF, 0x7) ; + if (state->TOP == 194) /* TOP == 19.4 */ + status += MXL_ControlWrite(fe, AGC_IF, 0x7); - if (Tuner->TOP == 212) // TOP == 21.2 - status += MXL_ControlWrite(Tuner, AGC_IF, 0x9) ; + if (state->TOP == 212) /* TOP == 21.2 */ + status += MXL_ControlWrite(fe, AGC_IF, 0x9); - if (Tuner->TOP == 232) // TOP == 23.2 - status += MXL_ControlWrite(Tuner, AGC_IF, 0xA) ; + if (state->TOP == 232) /* TOP == 23.2 */ + status += MXL_ControlWrite(fe, AGC_IF, 0xA); - if (Tuner->TOP == 252) // TOP == 25.2 - status += MXL_ControlWrite(Tuner, AGC_IF, 0xB) ; + if (state->TOP == 252) /* TOP == 25.2 */ + status += MXL_ControlWrite(fe, AGC_IF, 0xB); - if (Tuner->TOP == 271) // TOP == 27.1 - status += MXL_ControlWrite(Tuner, AGC_IF, 0xC) ; + if (state->TOP == 271) /* TOP == 27.1 */ + status += MXL_ControlWrite(fe, AGC_IF, 0xC); - if (Tuner->TOP == 292) // TOP == 29.2 - status += MXL_ControlWrite(Tuner, AGC_IF, 0xD) ; + if (state->TOP == 292) /* TOP == 29.2 */ + status += MXL_ControlWrite(fe, AGC_IF, 0xD); - if (Tuner->TOP == 317) // TOP == 31.7 - status += MXL_ControlWrite(Tuner, AGC_IF, 0xE) ; + if (state->TOP == 317) /* TOP == 31.7 */ + status += MXL_ControlWrite(fe, AGC_IF, 0xE); - if (Tuner->TOP == 349) // TOP == 34.9 - status += MXL_ControlWrite(Tuner, AGC_IF, 0xF) ; + if (state->TOP == 349) /* TOP == 34.9 */ + status += MXL_ControlWrite(fe, AGC_IF, 0xF); - // - // IF Synthesizer Control - // - status += MXL_IFSynthInit( Tuner ) ; + /* IF Synthesizer Control */ + status += MXL_IFSynthInit(fe); - // - // IF UpConverter Control - if (Tuner->IF_OUT_LOAD == 200) - { - status += MXL_ControlWrite(Tuner, DRV_RES_SEL, 6) ; - status += MXL_ControlWrite(Tuner, I_DRIVER, 2) ; + /* IF UpConverter Control */ + if (state->IF_OUT_LOAD == 200) { + status += MXL_ControlWrite(fe, DRV_RES_SEL, 6); + status += MXL_ControlWrite(fe, I_DRIVER, 2); } - if (Tuner->IF_OUT_LOAD == 300) - { - status += MXL_ControlWrite(Tuner, DRV_RES_SEL, 4) ; - status += MXL_ControlWrite(Tuner, I_DRIVER, 1) ; + if (state->IF_OUT_LOAD == 300) { + status += MXL_ControlWrite(fe, DRV_RES_SEL, 4); + status += MXL_ControlWrite(fe, I_DRIVER, 1); } - // - // Anti-Alias Filtering Control - // - // initialise Anti-Aliasing Filter - if (Tuner->Mode) {// Digital Mode - if (Tuner->IF_OUT >= 4000000UL && Tuner->IF_OUT <= 6280000UL) { - status += MXL_ControlWrite(Tuner, EN_AAF, 1) ; - status += MXL_ControlWrite(Tuner, EN_3P, 1) ; - status += MXL_ControlWrite(Tuner, EN_AUX_3P, 1) ; - status += MXL_ControlWrite(Tuner, SEL_AAF_BAND, 0) ; - } - if ((Tuner->IF_OUT == 36125000UL) || (Tuner->IF_OUT == 36150000UL)) { - status += MXL_ControlWrite(Tuner, EN_AAF, 1) ; - status += MXL_ControlWrite(Tuner, EN_3P, 1) ; - status += MXL_ControlWrite(Tuner, EN_AUX_3P, 1) ; - status += MXL_ControlWrite(Tuner, SEL_AAF_BAND, 1) ; - } - if (Tuner->IF_OUT > 36150000UL) { - status += MXL_ControlWrite(Tuner, EN_AAF, 0) ; - status += MXL_ControlWrite(Tuner, EN_3P, 1) ; - status += MXL_ControlWrite(Tuner, EN_AUX_3P, 1) ; - status += MXL_ControlWrite(Tuner, SEL_AAF_BAND, 1) ; - } - } else { // Analog Mode - if (Tuner->IF_OUT >= 4000000UL && Tuner->IF_OUT <= 5000000UL) + /* Anti-Alias Filtering Control + * initialise Anti-Aliasing Filter + */ + if (state->Mode) { /* Digital Mode */ + if (state->IF_OUT >= 4000000UL && state->IF_OUT <= 6280000UL) { + status += MXL_ControlWrite(fe, EN_AAF, 1); + status += MXL_ControlWrite(fe, EN_3P, 1); + status += MXL_ControlWrite(fe, EN_AUX_3P, 1); + status += MXL_ControlWrite(fe, SEL_AAF_BAND, 0); + } + if ((state->IF_OUT == 36125000UL) || (state->IF_OUT == 36150000UL)) { + status += MXL_ControlWrite(fe, EN_AAF, 1); + status += MXL_ControlWrite(fe, EN_3P, 1); + status += MXL_ControlWrite(fe, EN_AUX_3P, 1); + status += MXL_ControlWrite(fe, SEL_AAF_BAND, 1); + } + if (state->IF_OUT > 36150000UL) { + status += MXL_ControlWrite(fe, EN_AAF, 0); + status += MXL_ControlWrite(fe, EN_3P, 1); + status += MXL_ControlWrite(fe, EN_AUX_3P, 1); + status += MXL_ControlWrite(fe, SEL_AAF_BAND, 1); + } + } else { /* Analog Mode */ + if (state->IF_OUT >= 4000000UL && state->IF_OUT <= 5000000UL) { - status += MXL_ControlWrite(Tuner, EN_AAF, 1) ; - status += MXL_ControlWrite(Tuner, EN_3P, 1) ; - status += MXL_ControlWrite(Tuner, EN_AUX_3P, 1) ; - status += MXL_ControlWrite(Tuner, SEL_AAF_BAND, 0) ; + status += MXL_ControlWrite(fe, EN_AAF, 1); + status += MXL_ControlWrite(fe, EN_3P, 1); + status += MXL_ControlWrite(fe, EN_AUX_3P, 1); + status += MXL_ControlWrite(fe, SEL_AAF_BAND, 0); } - if (Tuner->IF_OUT > 5000000UL) + if (state->IF_OUT > 5000000UL) { - status += MXL_ControlWrite(Tuner, EN_AAF, 0) ; - status += MXL_ControlWrite(Tuner, EN_3P, 0) ; - status += MXL_ControlWrite(Tuner, EN_AUX_3P, 0) ; - status += MXL_ControlWrite(Tuner, SEL_AAF_BAND, 0) ; + status += MXL_ControlWrite(fe, EN_AAF, 0); + status += MXL_ControlWrite(fe, EN_3P, 0); + status += MXL_ControlWrite(fe, EN_AUX_3P, 0); + status += MXL_ControlWrite(fe, SEL_AAF_BAND, 0); } } - // - // Demod Clock Out - // - if (Tuner->CLOCK_OUT) - status += MXL_ControlWrite(Tuner, SEQ_ENCLK16_CLK_OUT, 1) ; + /* Demod Clock Out */ + if (state->CLOCK_OUT) + status += MXL_ControlWrite(fe, SEQ_ENCLK16_CLK_OUT, 1); else - status += MXL_ControlWrite(Tuner, SEQ_ENCLK16_CLK_OUT, 0) ; + status += MXL_ControlWrite(fe, SEQ_ENCLK16_CLK_OUT, 0); - if (Tuner->DIV_OUT == 1) - status += MXL_ControlWrite(Tuner, SEQ_SEL4_16B, 1) ; - if (Tuner->DIV_OUT == 0) - status += MXL_ControlWrite(Tuner, SEQ_SEL4_16B, 0) ; + if (state->DIV_OUT == 1) + status += MXL_ControlWrite(fe, SEQ_SEL4_16B, 1); + if (state->DIV_OUT == 0) + status += MXL_ControlWrite(fe, SEQ_SEL4_16B, 0); - // - // Crystal Control - // - if (Tuner->CAPSELECT) - status += MXL_ControlWrite(Tuner, XTAL_CAPSELECT, 1) ; + /* Crystal Control */ + if (state->CAPSELECT) + status += MXL_ControlWrite(fe, XTAL_CAPSELECT, 1); else - status += MXL_ControlWrite(Tuner, XTAL_CAPSELECT, 0) ; + status += MXL_ControlWrite(fe, XTAL_CAPSELECT, 0); - if (Tuner->Fxtal >= 12000000UL && Tuner->Fxtal <= 16000000UL) - status += MXL_ControlWrite(Tuner, IF_SEL_DBL, 1) ; - if (Tuner->Fxtal > 16000000UL && Tuner->Fxtal <= 32000000UL) - status += MXL_ControlWrite(Tuner, IF_SEL_DBL, 0) ; + if (state->Fxtal >= 12000000UL && state->Fxtal <= 16000000UL) + status += MXL_ControlWrite(fe, IF_SEL_DBL, 1); + if (state->Fxtal > 16000000UL && state->Fxtal <= 32000000UL) + status += MXL_ControlWrite(fe, IF_SEL_DBL, 0); - if (Tuner->Fxtal >= 12000000UL && Tuner->Fxtal <= 22000000UL) - status += MXL_ControlWrite(Tuner, RFSYN_R_DIV, 3) ; - if (Tuner->Fxtal > 22000000UL && Tuner->Fxtal <= 32000000UL) - status += MXL_ControlWrite(Tuner, RFSYN_R_DIV, 0) ; + if (state->Fxtal >= 12000000UL && state->Fxtal <= 22000000UL) + status += MXL_ControlWrite(fe, RFSYN_R_DIV, 3); + if (state->Fxtal > 22000000UL && state->Fxtal <= 32000000UL) + status += MXL_ControlWrite(fe, RFSYN_R_DIV, 0); - // - // Misc Controls - // - if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog LowIF mode - status += MXL_ControlWrite(Tuner, SEQ_EXTIQFSMPULSE, 0); + /* Misc Controls */ + if (state->Mode == 0 && Tuner->IF_Mode == 1) /* Analog LowIF mode */ + status += MXL_ControlWrite(fe, SEQ_EXTIQFSMPULSE, 0); else - status += MXL_ControlWrite(Tuner, SEQ_EXTIQFSMPULSE, 1); + status += MXL_ControlWrite(fe, SEQ_EXTIQFSMPULSE, 1); -// status += MXL_ControlRead(Tuner, IF_DIVVAL, &IF_DIVVAL_Val) ; + /* status += MXL_ControlRead(fe, IF_DIVVAL, &IF_DIVVAL_Val); */ - // Set TG_R_DIV - status += MXL_ControlWrite(Tuner, TG_R_DIV, MXL_Ceiling(Tuner->Fxtal, 1000000)) ; + /* Set TG_R_DIV */ + status += MXL_ControlWrite(fe, TG_R_DIV, MXL_Ceiling(state->Fxtal, 1000000)); - // - // Apply Default value to BB_INITSTATE_DLPF_TUNE - // + /* Apply Default value to BB_INITSTATE_DLPF_TUNE */ - // - // RSSI Control - // - if(Tuner->EN_RSSI) + /* RSSI Control */ + if (state->EN_RSSI) { - status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; - status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; - status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 1) ; - status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; - // RSSI reference point - status += MXL_ControlWrite(Tuner, RFA_RSSI_REF, 2) ; - status += MXL_ControlWrite(Tuner, RFA_RSSI_REFH, 3) ; - status += MXL_ControlWrite(Tuner, RFA_RSSI_REFL, 1) ; - // TOP point - status += MXL_ControlWrite(Tuner, RFA_FLR, 0) ; - status += MXL_ControlWrite(Tuner, RFA_CEIL, 12) ; + status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1); + status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1); + status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1); + status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1); + + /* RSSI reference point */ + status += MXL_ControlWrite(fe, RFA_RSSI_REF, 2); + status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 3); + status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 1); + + /* TOP point */ + status += MXL_ControlWrite(fe, RFA_FLR, 0); + status += MXL_ControlWrite(fe, RFA_CEIL, 12); } - // - // Modulation type bit settings - // Override the control values preset - // - if (Tuner->Mod_Type == MXL_DVBT) // DVB-T Mode + /* Modulation type bit settings + * Override the control values preset + */ + if (state->Mod_Type == MXL_DVBT) /* DVB-T Mode */ { - Tuner->AGC_Mode = 1 ; // Single AGC Mode - - // Enable RSSI - status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; - status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; - status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 1) ; - status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; - // RSSI reference point - status += MXL_ControlWrite(Tuner, RFA_RSSI_REF, 3) ; - status += MXL_ControlWrite(Tuner, RFA_RSSI_REFH, 5) ; - status += MXL_ControlWrite(Tuner, RFA_RSSI_REFL, 1) ; - // TOP point - status += MXL_ControlWrite(Tuner, RFA_FLR, 2) ; - status += MXL_ControlWrite(Tuner, RFA_CEIL, 13) ; - if (Tuner->IF_OUT <= 6280000UL) // Low IF - status += MXL_ControlWrite(Tuner, BB_IQSWAP, 0) ; - else // High IF - status += MXL_ControlWrite(Tuner, BB_IQSWAP, 1) ; + state->AGC_Mode = 1; /* Single AGC Mode */ + + /* Enable RSSI */ + status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1); + status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1); + status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1); + status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1); + + /* RSSI reference point */ + status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3); + status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5); + status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 1); + + /* TOP point */ + status += MXL_ControlWrite(fe, RFA_FLR, 2); + status += MXL_ControlWrite(fe, RFA_CEIL, 13); + if (state->IF_OUT <= 6280000UL) /* Low IF */ + status += MXL_ControlWrite(fe, BB_IQSWAP, 0); + else /* High IF */ + status += MXL_ControlWrite(fe, BB_IQSWAP, 1); } - if (Tuner->Mod_Type == MXL_ATSC) // ATSC Mode + if (state->Mod_Type == MXL_ATSC) /* ATSC Mode */ { - Tuner->AGC_Mode = 1 ; // Single AGC Mode - - // Enable RSSI - status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; - status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; - status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 1) ; - status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; - // RSSI reference point - status += MXL_ControlWrite(Tuner, RFA_RSSI_REF, 2) ; - status += MXL_ControlWrite(Tuner, RFA_RSSI_REFH, 4) ; - status += MXL_ControlWrite(Tuner, RFA_RSSI_REFL, 1) ; - // TOP point - status += MXL_ControlWrite(Tuner, RFA_FLR, 2) ; - status += MXL_ControlWrite(Tuner, RFA_CEIL, 13) ; - - status += MXL_ControlWrite(Tuner, BB_INITSTATE_DLPF_TUNE, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, 5) ; // Low Zero - if (Tuner->IF_OUT <= 6280000UL) // Low IF - status += MXL_ControlWrite(Tuner, BB_IQSWAP, 0) ; - else // High IF - status += MXL_ControlWrite(Tuner, BB_IQSWAP, 1) ; + Tuner->AGC_Mode = 1; /* Single AGC Mode */ + + /* Enable RSSI */ + status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1); + status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1); + status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1); + status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1); + + /* RSSI reference point */ + status += MXL_ControlWrite(fe, RFA_RSSI_REF, 2); + status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 4); + status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 1); + + /* TOP point */ + status += MXL_ControlWrite(fe, RFA_FLR, 2); + status += MXL_ControlWrite(fe, RFA_CEIL, 13); + status += MXL_ControlWrite(fe, BB_INITSTATE_DLPF_TUNE, 1); + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 5); /* Low Zero */ + if (state->IF_OUT <= 6280000UL) /* Low IF */ + status += MXL_ControlWrite(fe, BB_IQSWAP, 0); + else /* High IF */ + status += MXL_ControlWrite(fe, BB_IQSWAP, 1); } - if (Tuner->Mod_Type == MXL_QAM) // QAM Mode + if (state->Mod_Type == MXL_QAM) /* QAM Mode */ { - Tuner->Mode = MXL_DIGITAL_MODE; - - //Tuner->AGC_Mode = 1 ; // Single AGC Mode - - // Disable RSSI //change here for v2.6.5 - status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; - status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; - status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 0) ; - status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; - - // RSSI reference point - status += MXL_ControlWrite(Tuner, RFA_RSSI_REFH, 5) ; - status += MXL_ControlWrite(Tuner, RFA_RSSI_REF, 3) ; - status += MXL_ControlWrite(Tuner, RFA_RSSI_REFL, 2) ; - - status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, 3) ; //change here for v2.6.5 - - if (Tuner->IF_OUT <= 6280000UL) // Low IF - status += MXL_ControlWrite(Tuner, BB_IQSWAP, 0) ; - else // High IF - status += MXL_ControlWrite(Tuner, BB_IQSWAP, 1) ; + state->Mode = MXL_DIGITAL_MODE; + + /* state->AGC_Mode = 1; */ /* Single AGC Mode */ + + /* Disable RSSI */ /* change here for v2.6.5 */ + status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1); + status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1); + status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0); + status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1); + + /* RSSI reference point */ + status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5); + status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3); + status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 2); + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3); /* change here for v2.6.5 */ + + if (state->IF_OUT <= 6280000UL) /* Low IF */ + status += MXL_ControlWrite(fe, BB_IQSWAP, 0); + else /* High IF */ + status += MXL_ControlWrite(fe, BB_IQSWAP, 1); } - if (Tuner->Mod_Type == MXL_ANALOG_CABLE) // Analog Cable Mode - { - //Tuner->Mode = MXL_DIGITAL_MODE ; - Tuner->AGC_Mode = 1 ; // Single AGC Mode - - // Disable RSSI - status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; - status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; - status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 0) ; - status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; - - status += MXL_ControlWrite(Tuner, AGC_IF, 1) ; //change for 2.6.3 - status += MXL_ControlWrite(Tuner, AGC_RF, 15) ; - - status += MXL_ControlWrite(Tuner, BB_IQSWAP, 1) ; + if (state->Mod_Type == MXL_ANALOG_CABLE) { + /* Analog Cable Mode */ + /* Tuner->Mode = MXL_DIGITAL_MODE; */ + + state->AGC_Mode = 1; /* Single AGC Mode */ + + /* Disable RSSI */ + status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1); + status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1); + status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0); + status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1); + status += MXL_ControlWrite(fe, AGC_IF, 1); /* change for 2.6.3 */ + status += MXL_ControlWrite(fe, AGC_RF, 15); + status += MXL_ControlWrite(fe, BB_IQSWAP, 1); } - if (Tuner->Mod_Type == MXL_ANALOG_OTA) //Analog OTA Terrestrial mode add for 2.6.7 - { - //Tuner->Mode = MXL_ANALOG_MODE; - - // Enable RSSI - status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; - status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; - status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 1) ; - status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; - - // RSSI reference point - status += MXL_ControlWrite(Tuner, RFA_RSSI_REFH, 5) ; - status += MXL_ControlWrite(Tuner, RFA_RSSI_REF, 3) ; - status += MXL_ControlWrite(Tuner, RFA_RSSI_REFL, 2) ; - - status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, 3) ; - - status += MXL_ControlWrite(Tuner, BB_IQSWAP, 1) ; + if (state->Mod_Type == MXL_ANALOG_OTA) { + /* Analog OTA Terrestrial mode add for 2.6.7 */ + /* state->Mode = MXL_ANALOG_MODE; */ + + /* Enable RSSI */ + status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1); + status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1); + status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1); + status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1); + + /* RSSI reference point */ + status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5); + status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3); + status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 2); + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3); + status += MXL_ControlWrite(fe, BB_IQSWAP, 1); } - // RSSI disable - if(Tuner->EN_RSSI==0) - { - status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; - status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; - status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 0) ; - status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; + /* RSSI disable */ + if(state->EN_RSSI==0) { + status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1); + status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1); + status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0); + status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1); } - return status ; + return status; } /////////////////////////////////////////////////////////////////////////////// @@ -2456,9 +2278,9 @@ u16 MXL_IFSynthInit(Tuner_struct * Tuner) u32 fracModVal ; Kdbl = 2 ; - if (Tuner->Fxtal >= 12000000UL && Tuner->Fxtal <= 16000000UL) + if (state->Fxtal >= 12000000UL && state->Fxtal <= 16000000UL) Kdbl = 2 ; - if (Tuner->Fxtal > 16000000UL && Tuner->Fxtal <= 32000000UL) + if (state->Fxtal > 16000000UL && state->Fxtal <= 32000000UL) Kdbl = 1 ; // @@ -2467,43 +2289,43 @@ u16 MXL_IFSynthInit(Tuner_struct * Tuner) if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF mode { if (Tuner->IF_LO == 41000000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 328000000UL ; } if (Tuner->IF_LO == 47000000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 376000000UL ; } if (Tuner->IF_LO == 54000000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x10) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 324000000UL ; } if (Tuner->IF_LO == 60000000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x10) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 360000000UL ; } if (Tuner->IF_LO == 39250000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 314000000UL ; } if (Tuner->IF_LO == 39650000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 317200000UL ; } if (Tuner->IF_LO == 40150000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 321200000UL ; } if (Tuner->IF_LO == 40650000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 325200000UL ; } } @@ -2511,153 +2333,153 @@ u16 MXL_IFSynthInit(Tuner_struct * Tuner) if (Tuner->Mode || (Tuner->Mode == 0 && Tuner->IF_Mode == 0)) { if (Tuner->IF_LO == 57000000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x10) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 342000000UL ; } if (Tuner->IF_LO == 44000000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 352000000UL ; } if (Tuner->IF_LO == 43750000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 350000000UL ; } if (Tuner->IF_LO == 36650000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 366500000UL ; } if (Tuner->IF_LO == 36150000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 361500000UL ; } if (Tuner->IF_LO == 36000000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 360000000UL ; } if (Tuner->IF_LO == 35250000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 352500000UL ; } if (Tuner->IF_LO == 34750000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 347500000UL ; } if (Tuner->IF_LO == 6280000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x07) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 376800000UL ; } if (Tuner->IF_LO == 5000000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x09) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 360000000UL ; } if (Tuner->IF_LO == 4500000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x06) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 360000000UL ; } if (Tuner->IF_LO == 4570000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x06) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 365600000UL ; } if (Tuner->IF_LO == 4000000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x05) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x05) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 360000000UL ; } if (Tuner->IF_LO == 57400000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x10) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 344400000UL ; } if (Tuner->IF_LO == 44400000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 355200000UL ; } if (Tuner->IF_LO == 44150000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 353200000UL ; } if (Tuner->IF_LO == 37050000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 370500000UL ; } if (Tuner->IF_LO == 36550000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 365500000UL ; } if (Tuner->IF_LO == 36125000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 361250000UL ; } if (Tuner->IF_LO == 6000000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x07) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 360000000UL ; } if (Tuner->IF_LO == 5400000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x07) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 324000000UL ; } if (Tuner->IF_LO == 5380000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x07) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 322800000UL ; } if (Tuner->IF_LO == 5200000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x09) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 374400000UL ; } if (Tuner->IF_LO == 4900000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x09) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 352800000UL ; } if (Tuner->IF_LO == 4400000UL) { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x06) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 352000000UL ; } if (Tuner->IF_LO == 4063000UL) //add for 2.6.8 { - status += MXL_ControlWrite(Tuner, IF_DIVVAL, 0x05) ; - status += MXL_ControlWrite(Tuner, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x05) ; + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 365670000UL ; } } // CHCAL_INT_MOD_IF // CHCAL_FRAC_MOD_IF - intModVal = Fref / (Tuner->Fxtal * Kdbl/2) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_IF, intModVal ) ; + intModVal = Fref / (state->Fxtal * Kdbl/2) ; + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_IF, intModVal ) ; - fracModVal = (2<<15)*(Fref/1000 - (Tuner->Fxtal/1000 * Kdbl/2) * intModVal); - fracModVal = fracModVal / ((Tuner->Fxtal * Kdbl/2)/1000) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_IF, fracModVal) ; + fracModVal = (2<<15)*(Fref/1000 - (state->Fxtal/1000 * Kdbl/2) * intModVal); + fracModVal = fracModVal / ((state->Fxtal * Kdbl/2)/1000) ; + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_IF, fracModVal) ; return status ; } @@ -2706,7 +2528,7 @@ u32 MXL_GetXtalInt(u32 Xtal_Freq) // Functions used: // // MXL_SynthRFTGLO_Calc // // MXL5005_ControlWrite // -// MXL_GetXtalInt // +// MXL_GetXtalInt // // // // Inputs: // // Tuner : Tuner structure defined at higher level // @@ -2718,32 +2540,33 @@ u32 MXL_GetXtalInt(u32 Xtal_Freq) // 0 : Successful // // 1 : Unsuccessful // /////////////////////////////////////////////////////////////////////////////// -u16 MXL_TuneRF(Tuner_struct *Tuner, u32 RF_Freq) +u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) { + struct mxl5005s_state *state = fe->demodulator_priv; // Declare Local Variables - u16 status = 0 ; - u32 divider_val, E3, E4, E5, E5A ; - u32 Fmax, Fmin, FmaxBin, FminBin ; + u16 status = 0; + u32 divider_val, E3, E4, E5, E5A; + u32 Fmax, Fmin, FmaxBin, FminBin; u32 Kdbl_RF = 2; - u32 tg_divval ; - u32 tg_lo ; - u32 Xtal_Int ; + u32 tg_divval; + u32 tg_lo; + u32 Xtal_Int; u32 Fref_TG; u32 Fvco; // u32 temp; - Xtal_Int = MXL_GetXtalInt(Tuner->Fxtal ) ; + Xtal_Int = MXL_GetXtalInt(state->Fxtal); - Tuner->RF_IN = RF_Freq ; + state->RF_IN = RF_Freq; - MXL_SynthRFTGLO_Calc( Tuner ) ; + MXL_SynthRFTGLO_Calc(fe); - if (Tuner->Fxtal >= 12000000UL && Tuner->Fxtal <= 22000000UL) - Kdbl_RF = 2 ; - if (Tuner->Fxtal > 22000000 && Tuner->Fxtal <= 32000000) - Kdbl_RF = 1 ; + if (state->Fxtal >= 12000000UL && state->Fxtal <= 22000000UL) + Kdbl_RF = 2; + if (state->Fxtal > 22000000 && state->Fxtal <= 32000000) + Kdbl_RF = 1; // // Downconverter Controls @@ -2755,133 +2578,133 @@ u16 MXL_TuneRF(Tuner_struct *Tuner, u32 RF_Freq) // DN_EN_VHFUHFBAR // DN_GAIN_ADJUST // Change the boundary reference from RF_IN to RF_LO - if (Tuner->RF_LO < 40000000UL) { + if (state->RF_LO < 40000000UL) { return -1; } - if (Tuner->RF_LO >= 40000000UL && Tuner->RF_LO <= 75000000UL) { + if (state->RF_LO >= 40000000UL && state->RF_LO <= 75000000UL) { // Look-Up Table implementation - status += MXL_ControlWrite(Tuner, DN_POLY, 2) ; - status += MXL_ControlWrite(Tuner, DN_RFGAIN, 3) ; - status += MXL_ControlWrite(Tuner, DN_CAP_RFLPF, 423) ; - status += MXL_ControlWrite(Tuner, DN_EN_VHFUHFBAR, 1) ; - status += MXL_ControlWrite(Tuner, DN_GAIN_ADJUST, 1) ; + status += MXL_ControlWrite(fe, DN_POLY, 2); + status += MXL_ControlWrite(fe, DN_RFGAIN, 3); + status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 423); + status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 1); + status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 1); } - if (Tuner->RF_LO > 75000000UL && Tuner->RF_LO <= 100000000UL) { + if (state->RF_LO > 75000000UL && state->RF_LO <= 100000000UL) { // Look-Up Table implementation - status += MXL_ControlWrite(Tuner, DN_POLY, 3) ; - status += MXL_ControlWrite(Tuner, DN_RFGAIN, 3) ; - status += MXL_ControlWrite(Tuner, DN_CAP_RFLPF, 222) ; - status += MXL_ControlWrite(Tuner, DN_EN_VHFUHFBAR, 1) ; - status += MXL_ControlWrite(Tuner, DN_GAIN_ADJUST, 1) ; + status += MXL_ControlWrite(fe, DN_POLY, 3); + status += MXL_ControlWrite(fe, DN_RFGAIN, 3); + status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 222); + status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 1); + status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 1); } - if (Tuner->RF_LO > 100000000UL && Tuner->RF_LO <= 150000000UL) { + if (state->RF_LO > 100000000UL && state->RF_LO <= 150000000UL) { // Look-Up Table implementation - status += MXL_ControlWrite(Tuner, DN_POLY, 3) ; - status += MXL_ControlWrite(Tuner, DN_RFGAIN, 3) ; - status += MXL_ControlWrite(Tuner, DN_CAP_RFLPF, 147) ; - status += MXL_ControlWrite(Tuner, DN_EN_VHFUHFBAR, 1) ; - status += MXL_ControlWrite(Tuner, DN_GAIN_ADJUST, 2) ; + status += MXL_ControlWrite(fe, DN_POLY, 3); + status += MXL_ControlWrite(fe, DN_RFGAIN, 3); + status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 147); + status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 1); + status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 2); } - if (Tuner->RF_LO > 150000000UL && Tuner->RF_LO <= 200000000UL) { + if (state->RF_LO > 150000000UL && state->RF_LO <= 200000000UL) { // Look-Up Table implementation - status += MXL_ControlWrite(Tuner, DN_POLY, 3) ; - status += MXL_ControlWrite(Tuner, DN_RFGAIN, 3) ; - status += MXL_ControlWrite(Tuner, DN_CAP_RFLPF, 9) ; - status += MXL_ControlWrite(Tuner, DN_EN_VHFUHFBAR, 1) ; - status += MXL_ControlWrite(Tuner, DN_GAIN_ADJUST, 2) ; + status += MXL_ControlWrite(fe, DN_POLY, 3); + status += MXL_ControlWrite(fe, DN_RFGAIN, 3); + status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 9); + status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 1); + status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 2); } - if (Tuner->RF_LO > 200000000UL && Tuner->RF_LO <= 300000000UL) { + if (state->RF_LO > 200000000UL && state->RF_LO <= 300000000UL) { // Look-Up Table implementation - status += MXL_ControlWrite(Tuner, DN_POLY, 3) ; - status += MXL_ControlWrite(Tuner, DN_RFGAIN, 3) ; - status += MXL_ControlWrite(Tuner, DN_CAP_RFLPF, 0) ; - status += MXL_ControlWrite(Tuner, DN_EN_VHFUHFBAR, 1) ; - status += MXL_ControlWrite(Tuner, DN_GAIN_ADJUST, 3) ; + status += MXL_ControlWrite(fe, DN_POLY, 3) ; + status += MXL_ControlWrite(fe, DN_RFGAIN, 3) ; + status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 0) ; + status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 1) ; + status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 3) ; } - if (Tuner->RF_LO > 300000000UL && Tuner->RF_LO <= 650000000UL) { + if (state->RF_LO > 300000000UL && state->RF_LO <= 650000000UL) { // Look-Up Table implementation - status += MXL_ControlWrite(Tuner, DN_POLY, 3) ; - status += MXL_ControlWrite(Tuner, DN_RFGAIN, 1) ; - status += MXL_ControlWrite(Tuner, DN_CAP_RFLPF, 0) ; - status += MXL_ControlWrite(Tuner, DN_EN_VHFUHFBAR, 0) ; - status += MXL_ControlWrite(Tuner, DN_GAIN_ADJUST, 3) ; + status += MXL_ControlWrite(fe, DN_POLY, 3) ; + status += MXL_ControlWrite(fe, DN_RFGAIN, 1) ; + status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 0) ; + status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 0) ; + status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 3) ; } - if (Tuner->RF_LO > 650000000UL && Tuner->RF_LO <= 900000000UL) { + if (state->RF_LO > 650000000UL && state->RF_LO <= 900000000UL) { // Look-Up Table implementation - status += MXL_ControlWrite(Tuner, DN_POLY, 3) ; - status += MXL_ControlWrite(Tuner, DN_RFGAIN, 2) ; - status += MXL_ControlWrite(Tuner, DN_CAP_RFLPF, 0) ; - status += MXL_ControlWrite(Tuner, DN_EN_VHFUHFBAR, 0) ; - status += MXL_ControlWrite(Tuner, DN_GAIN_ADJUST, 3) ; + status += MXL_ControlWrite(fe, DN_POLY, 3) ; + status += MXL_ControlWrite(fe, DN_RFGAIN, 2) ; + status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 0) ; + status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 0) ; + status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 3) ; } - if (Tuner->RF_LO > 900000000UL) { + if (state->RF_LO > 900000000UL) { return -1; } // DN_IQTNBUF_AMP // DN_IQTNGNBFBIAS_BST - if (Tuner->RF_LO >= 40000000UL && Tuner->RF_LO <= 75000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + if (state->RF_LO >= 40000000UL && state->RF_LO <= 75000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); } - if (Tuner->RF_LO > 75000000UL && Tuner->RF_LO <= 100000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + if (state->RF_LO > 75000000UL && state->RF_LO <= 100000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); } - if (Tuner->RF_LO > 100000000UL && Tuner->RF_LO <= 150000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + if (state->RF_LO > 100000000UL && state->RF_LO <= 150000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); } - if (Tuner->RF_LO > 150000000UL && Tuner->RF_LO <= 200000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + if (state->RF_LO > 150000000UL && state->RF_LO <= 200000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); } - if (Tuner->RF_LO > 200000000UL && Tuner->RF_LO <= 300000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + if (state->RF_LO > 200000000UL && state->RF_LO <= 300000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); } - if (Tuner->RF_LO > 300000000UL && Tuner->RF_LO <= 400000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + if (state->RF_LO > 300000000UL && state->RF_LO <= 400000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); } - if (Tuner->RF_LO > 400000000UL && Tuner->RF_LO <= 450000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + if (state->RF_LO > 400000000UL && state->RF_LO <= 450000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); } - if (Tuner->RF_LO > 450000000UL && Tuner->RF_LO <= 500000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + if (state->RF_LO > 450000000UL && state->RF_LO <= 500000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); } - if (Tuner->RF_LO > 500000000UL && Tuner->RF_LO <= 550000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + if (state->RF_LO > 500000000UL && state->RF_LO <= 550000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); } - if (Tuner->RF_LO > 550000000UL && Tuner->RF_LO <= 600000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + if (state->RF_LO > 550000000UL && state->RF_LO <= 600000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); } - if (Tuner->RF_LO > 600000000UL && Tuner->RF_LO <= 650000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + if (state->RF_LO > 600000000UL && state->RF_LO <= 650000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); } - if (Tuner->RF_LO > 650000000UL && Tuner->RF_LO <= 700000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + if (state->RF_LO > 650000000UL && state->RF_LO <= 700000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); } - if (Tuner->RF_LO > 700000000UL && Tuner->RF_LO <= 750000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + if (state->RF_LO > 700000000UL && state->RF_LO <= 750000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); } - if (Tuner->RF_LO > 750000000UL && Tuner->RF_LO <= 800000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 1) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 0) ; + if (state->RF_LO > 750000000UL && state->RF_LO <= 800000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); } - if (Tuner->RF_LO > 800000000UL && Tuner->RF_LO <= 850000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 10) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 1) ; + if (state->RF_LO > 800000000UL && state->RF_LO <= 850000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 10); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 1); } - if (Tuner->RF_LO > 850000000UL && Tuner->RF_LO <= 900000000UL) { - status += MXL_ControlWrite(Tuner, DN_IQTNBUF_AMP, 10) ; - status += MXL_ControlWrite(Tuner, DN_IQTNGNBFBIAS_BST, 1) ; + if (state->RF_LO > 850000000UL && state->RF_LO <= 900000000UL) { + status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 10); + status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 1); } // @@ -2898,143 +2721,143 @@ u16 MXL_TuneRF(Tuner_struct *Tuner, u32 RF_Freq) // Set divider_val, Fmax, Fmix to use in Equations FminBin = 28000000UL ; FmaxBin = 42500000UL ; - if (Tuner->RF_LO >= 40000000UL && Tuner->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 1) ; + if (state->RF_LO >= 40000000UL && state->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 1); divider_val = 64 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 42500000UL ; FmaxBin = 56000000UL ; - if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 1) ; + if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 1); divider_val = 64 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 56000000UL ; FmaxBin = 85000000UL ; - if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 1) ; + if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 1) ; divider_val = 32 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 85000000UL ; FmaxBin = 112000000UL ; - if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 1) ; + if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 1) ; divider_val = 32 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 112000000UL ; FmaxBin = 170000000UL ; - if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 2) ; + if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 2) ; divider_val = 16 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 170000000UL ; FmaxBin = 225000000UL ; - if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 2) ; + if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 2) ; divider_val = 16 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 225000000UL ; FmaxBin = 300000000UL ; - if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 4) ; + if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 4) ; divider_val = 8 ; Fmax = 340000000UL ; Fmin = FminBin ; } FminBin = 300000000UL ; FmaxBin = 340000000UL ; - if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0) ; + if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 1) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 0) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0) ; divider_val = 8 ; Fmax = FmaxBin ; Fmin = 225000000UL ; } FminBin = 340000000UL ; FmaxBin = 450000000UL ; - if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 2) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0) ; + if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 1) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 0) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0) ; + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 2) ; + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0) ; divider_val = 8 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 450000000UL ; FmaxBin = 680000000UL ; - if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0) ; + if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 1) ; + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0) ; divider_val = 4 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 680000000UL ; FmaxBin = 900000000UL ; - if (Tuner->RF_LO > FminBin && Tuner->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 1) ; - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0) ; + if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1) ; + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 1) ; + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0) ; divider_val = 4 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -3047,32 +2870,32 @@ u16 MXL_TuneRF(Tuner_struct *Tuner, u32 RF_Freq) // Equation E3 // RFSYN_VCO_BIAS - E3 = (((Fmax-Tuner->RF_LO)/1000)*32)/((Fmax-Fmin)/1000) + 8 ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, E3) ; + E3 = (((Fmax-state->RF_LO)/1000)*32)/((Fmax-Fmin)/1000) + 8 ; + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, E3) ; // Equation E4 // CHCAL_INT_MOD_RF - E4 = (Tuner->RF_LO*divider_val/1000)/(2*Tuner->Fxtal*Kdbl_RF/1000) ; - MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, E4) ; + E4 = (state->RF_LO*divider_val/1000)/(2*state->Fxtal*Kdbl_RF/1000) ; + MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, E4) ; // Equation E5 // CHCAL_FRAC_MOD_RF // CHCAL_EN_INT_RF - E5 = ((2<<17)*(Tuner->RF_LO/10000*divider_val - (E4*(2*Tuner->Fxtal*Kdbl_RF)/10000)))/(2*Tuner->Fxtal*Kdbl_RF/10000) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, E5) ; + E5 = ((2<<17)*(state->RF_LO/10000*divider_val - (E4*(2*state->Fxtal*Kdbl_RF)/10000)))/(2*state->Fxtal*Kdbl_RF/10000) ; + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, E5) ; // Equation E5A // RFSYN_LPF_R - E5A = (((Fmax - Tuner->RF_LO)/1000)*4/((Fmax-Fmin)/1000)) + 1 ; - status += MXL_ControlWrite(Tuner, RFSYN_LPF_R, E5A) ; + E5A = (((Fmax - state->RF_LO)/1000)*4/((Fmax-Fmin)/1000)) + 1 ; + status += MXL_ControlWrite(fe, RFSYN_LPF_R, E5A) ; // Euqation E5B // CHCAL_EN_INIT_RF - status += MXL_ControlWrite(Tuner, CHCAL_EN_INT_RF, ((E5 == 0) ? 1 : 0)); + status += MXL_ControlWrite(fe, CHCAL_EN_INT_RF, ((E5 == 0) ? 1 : 0)); //if (E5 == 0) - // status += MXL_ControlWrite(Tuner, CHCAL_EN_INT_RF, 1); + // status += MXL_ControlWrite(fe, CHCAL_EN_INT_RF, 1); //else - // status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, E5) ; + // status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, E5) ; // // Set TG Synth @@ -3082,98 +2905,98 @@ u16 MXL_TuneRF(Tuner_struct *Tuner, u32 RF_Freq) // TG_LO_SELVAL // // Set divider_val, Fmax, Fmix to use in Equations - if (Tuner->TG_LO < 33000000UL) { + if (state->TG_LO < 33000000UL) { return -1; } FminBin = 33000000UL ; FmaxBin = 50000000UL ; - if (Tuner->TG_LO >= FminBin && Tuner->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x6) ; - status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x0) ; + if (state->TG_LO >= FminBin && state->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x6) ; + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x0) ; divider_val = 36 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 50000000UL ; FmaxBin = 67000000UL ; - if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x1) ; - status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x0) ; + if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x1) ; + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x0) ; divider_val = 24 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 67000000UL ; FmaxBin = 100000000UL ; - if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0xC) ; - status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x2) ; + if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0xC) ; + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x2) ; divider_val = 18 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 100000000UL ; FmaxBin = 150000000UL ; - if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x8) ; - status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x2) ; + if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x8) ; + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x2) ; divider_val = 12 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 150000000UL ; FmaxBin = 200000000UL ; - if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x0) ; - status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x2) ; + if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x0) ; + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x2) ; divider_val = 8 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 200000000UL ; FmaxBin = 300000000UL ; - if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x8) ; - status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x3) ; + if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x8) ; + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x3) ; divider_val = 6 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 300000000UL ; FmaxBin = 400000000UL ; - if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x0) ; - status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x3) ; + if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x0) ; + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x3) ; divider_val = 4 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 400000000UL ; FmaxBin = 600000000UL ; - if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x8) ; - status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x7) ; + if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x8) ; + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x7) ; divider_val = 3 ; Fmax = FmaxBin ; Fmin = FminBin ; } FminBin = 600000000UL ; FmaxBin = 900000000UL ; - if (Tuner->TG_LO > FminBin && Tuner->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(Tuner, TG_LO_DIVVAL, 0x0) ; - status += MXL_ControlWrite(Tuner, TG_LO_SELVAL, 0x7) ; + if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x0) ; + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x7) ; divider_val = 2 ; Fmax = FmaxBin ; Fmin = FminBin ; } // TG_DIV_VAL - tg_divval = (Tuner->TG_LO*divider_val/100000) - *(MXL_Ceiling(Tuner->Fxtal,1000000) * 100) / (Tuner->Fxtal/1000) ; - status += MXL_ControlWrite(Tuner, TG_DIV_VAL, tg_divval) ; + tg_divval = (state->TG_LO*divider_val/100000) + *(MXL_Ceiling(state->Fxtal,1000000) * 100) / (state->Fxtal/1000) ; + status += MXL_ControlWrite(fe, TG_DIV_VAL, tg_divval) ; - if (Tuner->TG_LO > 600000000UL) - status += MXL_ControlWrite(Tuner, TG_DIV_VAL, tg_divval + 1 ) ; + if (state->TG_LO > 600000000UL) + status += MXL_ControlWrite(fe, TG_DIV_VAL, tg_divval + 1 ) ; Fmax = 1800000000UL ; Fmin = 1200000000UL ; @@ -3181,28 +3004,28 @@ u16 MXL_TuneRF(Tuner_struct *Tuner, u32 RF_Freq) // to prevent overflow of 32 bit unsigned integer, use following equation. Edit for v2.6.4 - Fref_TG = (Tuner->Fxtal/1000)/ MXL_Ceiling(Tuner->Fxtal, 1000000) ; // Fref_TF = Fref_TG*1000 + Fref_TG = (state->Fxtal/1000)/ MXL_Ceiling(state->Fxtal, 1000000) ; // Fref_TF = Fref_TG*1000 - Fvco = (Tuner->TG_LO/10000) * divider_val * Fref_TG; //Fvco = Fvco/10 + Fvco = (state->TG_LO/10000) * divider_val * Fref_TG; //Fvco = Fvco/10 tg_lo = (((Fmax/10 - Fvco)/100)*32) / ((Fmax-Fmin)/1000)+8; //below equation is same as above but much harder to debug. - //tg_lo = ( ((Fmax/10000 * Xtal_Int)/100) - ((Tuner->TG_LO/10000)*divider_val*(Tuner->Fxtal/10000)/100) )*32/((Fmax-Fmin)/10000 * Xtal_Int/100) + 8 ; + //tg_lo = ( ((Fmax/10000 * Xtal_Int)/100) - ((state->TG_LO/10000)*divider_val*(state->Fxtal/10000)/100) )*32/((Fmax-Fmin)/10000 * Xtal_Int/100) + 8 ; - status += MXL_ControlWrite(Tuner, TG_VCO_BIAS , tg_lo) ; + status += MXL_ControlWrite(fe, TG_VCO_BIAS , tg_lo) ; //add for 2.6.5 //Special setting for QAM - if(Tuner ->Mod_Type == MXL_QAM) + if(state->Mod_Type == MXL_QAM) { - if(Tuner->RF_IN < 680000000) - status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, 3) ; + if(state->RF_IN < 680000000) + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3) ; else - status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, 2) ; + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 2) ; } @@ -3213,673 +3036,675 @@ u16 MXL_TuneRF(Tuner_struct *Tuner, u32 RF_Freq) // if (Tuner->TF_Type == MXL_TF_OFF) // Tracking Filter Off State; turn off all the banks { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; - status += MXL_SetGPIO(Tuner, 3, 1) ; // turn off Bank 1 - status += MXL_SetGPIO(Tuner, 1, 1) ; // turn off Bank 2 - status += MXL_SetGPIO(Tuner, 4, 1) ; // turn off Bank 3 + status += MXL_SetGPIO(fe, 3, 1) ; // turn off Bank 1 + status += MXL_SetGPIO(fe, 1, 1) ; // turn off Bank 2 + status += MXL_SetGPIO(fe, 4, 1) ; // turn off Bank 3 } if (Tuner->TF_Type == MXL_TF_C) // Tracking Filter type C { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; - status += MXL_ControlWrite(Tuner, DAC_DIN_A, 0) ; + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; + status += MXL_ControlWrite(fe, DAC_DIN_A, 0) ; - if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 150000000) + if (state->RF_IN >= 43000000 && state->RF_IN < 150000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; + status += MXL_SetGPIO(fe, 3, 0) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 150000000 && Tuner->RF_IN < 280000000) + if (state->RF_IN >= 150000000 && state->RF_IN < 280000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; + status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 280000000 && Tuner->RF_IN < 360000000) + if (state->RF_IN >= 280000000 && state->RF_IN < 360000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; + status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 4, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 360000000 && Tuner->RF_IN < 560000000) + if (state->RF_IN >= 360000000 && state->RF_IN < 560000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; + status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 560000000 && Tuner->RF_IN < 580000000) + if (state->RF_IN >= 560000000 && state->RF_IN < 580000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 29) ; - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_ControlWrite(fe, DAC_DIN_B, 29) ; + status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 580000000 && Tuner->RF_IN < 630000000) + if (state->RF_IN >= 580000000 && state->RF_IN < 630000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; + status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 630000000 && Tuner->RF_IN < 700000000) + if (state->RF_IN >= 630000000 && state->RF_IN < 700000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 16) ; - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_ControlWrite(fe, DAC_DIN_B, 16) ; + status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 700000000 && Tuner->RF_IN < 760000000) + if (state->RF_IN >= 700000000 && state->RF_IN < 760000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 7) ; - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_ControlWrite(fe, DAC_DIN_B, 7) ; + status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 760000000 && Tuner->RF_IN <= 900000000) + if (state->RF_IN >= 760000000 && state->RF_IN <= 900000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; + status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank3 Off } } if (Tuner->TF_Type == MXL_TF_C_H) // Tracking Filter type C-H for Hauppauge only { - status += MXL_ControlWrite(Tuner, DAC_DIN_A, 0) ; + status += MXL_ControlWrite(fe, DAC_DIN_A, 0) ; - if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 150000000) + if (state->RF_IN >= 43000000 && state->RF_IN < 150000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(fe, 3, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 150000000 && Tuner->RF_IN < 280000000) + if (state->RF_IN >= 150000000 && state->RF_IN < 280000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 1, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 280000000 && Tuner->RF_IN < 360000000) + if (state->RF_IN >= 280000000 && state->RF_IN < 360000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 1, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 360000000 && Tuner->RF_IN < 560000000) + if (state->RF_IN >= 360000000 && state->RF_IN < 560000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 560000000 && Tuner->RF_IN < 580000000) + if (state->RF_IN >= 560000000 && state->RF_IN < 580000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 580000000 && Tuner->RF_IN < 630000000) + if (state->RF_IN >= 580000000 && state->RF_IN < 630000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 630000000 && Tuner->RF_IN < 700000000) + if (state->RF_IN >= 630000000 && state->RF_IN < 700000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 700000000 && Tuner->RF_IN < 760000000) + if (state->RF_IN >= 700000000 && state->RF_IN < 760000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 760000000 && Tuner->RF_IN <= 900000000) + if (state->RF_IN >= 760000000 && state->RF_IN <= 900000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank3 Off } } if (Tuner->TF_Type == MXL_TF_D) // Tracking Filter type D { - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 174000000) + if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 174000000 && Tuner->RF_IN < 250000000) + if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 250000000 && Tuner->RF_IN < 310000000) + if (state->RF_IN >= 250000000 && state->RF_IN < 310000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 310000000 && Tuner->RF_IN < 360000000) + if (state->RF_IN >= 310000000 && state->RF_IN < 360000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 360000000 && Tuner->RF_IN < 470000000) + if (state->RF_IN >= 360000000 && state->RF_IN < 470000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 470000000 && Tuner->RF_IN < 640000000) + if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 640000000 && Tuner->RF_IN <= 900000000) + if (state->RF_IN >= 640000000 && state->RF_IN <= 900000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } } if (Tuner->TF_Type == MXL_TF_D_L) // Tracking Filter type D-L for Lumanate ONLY change for 2.6.3 { - status += MXL_ControlWrite(Tuner, DAC_DIN_A, 0) ; + status += MXL_ControlWrite(fe, DAC_DIN_A, 0) ; // if UHF and terrestrial => Turn off Tracking Filter - if (Tuner->RF_IN >= 471000000 && (Tuner->RF_IN - 471000000)%6000000 != 0) + if (state->RF_IN >= 471000000 && (state->RF_IN - 471000000)%6000000 != 0) { // Turn off all the banks - status += MXL_SetGPIO(Tuner, 3, 1) ; - status += MXL_SetGPIO(Tuner, 1, 1) ; - status += MXL_SetGPIO(Tuner, 4, 1) ; - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; + status += MXL_SetGPIO(fe, 3, 1) ; + status += MXL_SetGPIO(fe, 1, 1) ; + status += MXL_SetGPIO(fe, 4, 1) ; + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; - status += MXL_ControlWrite(Tuner, AGC_IF, 10) ; + status += MXL_ControlWrite(fe, AGC_IF, 10) ; } else // if VHF or cable => Turn on Tracking Filter { - if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 140000000) + if (state->RF_IN >= 43000000 && state->RF_IN < 140000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 Off } - if (Tuner->RF_IN >= 140000000 && Tuner->RF_IN < 240000000) + if (state->RF_IN >= 140000000 && state->RF_IN < 240000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 Off } - if (Tuner->RF_IN >= 240000000 && Tuner->RF_IN < 340000000) + if (state->RF_IN >= 240000000 && state->RF_IN < 340000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 Off } - if (Tuner->RF_IN >= 340000000 && Tuner->RF_IN < 430000000) + if (state->RF_IN >= 340000000 && state->RF_IN < 430000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 On } - if (Tuner->RF_IN >= 430000000 && Tuner->RF_IN < 470000000) + if (state->RF_IN >= 430000000 && state->RF_IN < 470000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 On } - if (Tuner->RF_IN >= 470000000 && Tuner->RF_IN < 570000000) + if (state->RF_IN >= 470000000 && state->RF_IN < 570000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 On } - if (Tuner->RF_IN >= 570000000 && Tuner->RF_IN < 620000000) + if (state->RF_IN >= 570000000 && state->RF_IN < 620000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 0) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Offq + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Offq } - if (Tuner->RF_IN >= 620000000 && Tuner->RF_IN < 760000000) + if (state->RF_IN >= 620000000 && state->RF_IN < 760000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 760000000 && Tuner->RF_IN <= 900000000) + if (state->RF_IN >= 760000000 && state->RF_IN <= 900000000) { - status += MXL_ControlWrite(Tuner, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } } } if (Tuner->TF_Type == MXL_TF_E) // Tracking Filter type E { - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 174000000) + if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 174000000 && Tuner->RF_IN < 250000000) + if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 250000000 && Tuner->RF_IN < 310000000) + if (state->RF_IN >= 250000000 && state->RF_IN < 310000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 310000000 && Tuner->RF_IN < 360000000) + if (state->RF_IN >= 310000000 && state->RF_IN < 360000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 360000000 && Tuner->RF_IN < 470000000) + if (state->RF_IN >= 360000000 && state->RF_IN < 470000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 470000000 && Tuner->RF_IN < 640000000) + if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 640000000 && Tuner->RF_IN <= 900000000) + if (state->RF_IN >= 640000000 && state->RF_IN <= 900000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } } if (Tuner->TF_Type == MXL_TF_F) // Tracking Filter type F { - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 160000000) + if (state->RF_IN >= 43000000 && state->RF_IN < 160000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 160000000 && Tuner->RF_IN < 210000000) + if (state->RF_IN >= 160000000 && state->RF_IN < 210000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 210000000 && Tuner->RF_IN < 300000000) + if (state->RF_IN >= 210000000 && state->RF_IN < 300000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 300000000 && Tuner->RF_IN < 390000000) + if (state->RF_IN >= 300000000 && state->RF_IN < 390000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 390000000 && Tuner->RF_IN < 515000000) + if (state->RF_IN >= 390000000 && state->RF_IN < 515000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 515000000 && Tuner->RF_IN < 650000000) + if (state->RF_IN >= 515000000 && state->RF_IN < 650000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 650000000 && Tuner->RF_IN <= 900000000) + if (state->RF_IN >= 650000000 && state->RF_IN <= 900000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } } if (Tuner->TF_Type == MXL_TF_E_2) // Tracking Filter type E_2 { - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 174000000) + if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 174000000 && Tuner->RF_IN < 250000000) + if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 250000000 && Tuner->RF_IN < 350000000) + if (state->RF_IN >= 250000000 && state->RF_IN < 350000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 350000000 && Tuner->RF_IN < 400000000) + if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 400000000 && Tuner->RF_IN < 570000000) + if (state->RF_IN >= 400000000 && state->RF_IN < 570000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 570000000 && Tuner->RF_IN < 770000000) + if (state->RF_IN >= 570000000 && state->RF_IN < 770000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 770000000 && Tuner->RF_IN <= 900000000) + if (state->RF_IN >= 770000000 && state->RF_IN <= 900000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } } if (Tuner->TF_Type == MXL_TF_G) // Tracking Filter type G add for v2.6.8 { - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - if (Tuner->RF_IN >= 50000000 && Tuner->RF_IN < 190000000) + if (state->RF_IN >= 50000000 && state->RF_IN < 190000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 190000000 && Tuner->RF_IN < 280000000) + if (state->RF_IN >= 190000000 && state->RF_IN < 280000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 280000000 && Tuner->RF_IN < 350000000) + if (state->RF_IN >= 280000000 && state->RF_IN < 350000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 350000000 && Tuner->RF_IN < 400000000) + if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 400000000 && Tuner->RF_IN < 470000000) //modified for 2.6.11 + if (state->RF_IN >= 400000000 && state->RF_IN < 470000000) //modified for 2.6.11 { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 470000000 && Tuner->RF_IN < 640000000) + if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 640000000 && Tuner->RF_IN < 820000000) + if (state->RF_IN >= 640000000 && state->RF_IN < 820000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 820000000 && Tuner->RF_IN <= 900000000) + if (state->RF_IN >= 820000000 && state->RF_IN <= 900000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } } if (Tuner->TF_Type == MXL_TF_E_NA) // Tracking Filter type E-NA for Empia ONLY change for 2.6.8 { - status += MXL_ControlWrite(Tuner, DAC_DIN_B, 0) ; + status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; // if UHF and terrestrial=> Turn off Tracking Filter - if (Tuner->RF_IN >= 471000000 && (Tuner->RF_IN - 471000000)%6000000 != 0) + if (state->RF_IN >= 471000000 && (state->RF_IN - 471000000)%6000000 != 0) { // Turn off all the banks - status += MXL_SetGPIO(Tuner, 3, 1) ; - status += MXL_SetGPIO(Tuner, 1, 1) ; - status += MXL_SetGPIO(Tuner, 4, 1) ; - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; + status += MXL_SetGPIO(fe, 3, 1) ; + status += MXL_SetGPIO(fe, 1, 1) ; + status += MXL_SetGPIO(fe, 4, 1) ; + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; //2.6.12 //Turn on RSSI - status += MXL_ControlWrite(Tuner, SEQ_EXTSYNTHCALIF, 1) ; - status += MXL_ControlWrite(Tuner, SEQ_EXTDCCAL, 1) ; - status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 1) ; - status += MXL_ControlWrite(Tuner, RFA_ENCLKRFAGC, 1) ; + status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1) ; + status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1) ; + status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1) ; + status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1) ; // RSSI reference point - status += MXL_ControlWrite(Tuner, RFA_RSSI_REFH, 5) ; - status += MXL_ControlWrite(Tuner, RFA_RSSI_REF, 3) ; - status += MXL_ControlWrite(Tuner, RFA_RSSI_REFL, 2) ; + status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5) ; + status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3) ; + status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 2) ; - //status += MXL_ControlWrite(Tuner, AGC_IF, 10) ; //doesn't matter since RSSI is turn on + //status += MXL_ControlWrite(fe, AGC_IF, 10) ; //doesn't matter since RSSI is turn on //following parameter is from analog OTA mode, can be change to seek better performance - status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, 3) ; + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3) ; } else //if VHF or Cable => Turn on Tracking Filter { //2.6.12 //Turn off RSSI - status += MXL_ControlWrite(Tuner, AGC_EN_RSSI, 0) ; + status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0) ; //change back from above condition - status += MXL_ControlWrite(Tuner, RFSYN_CHP_GAIN, 5) ; + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 5) ; - if (Tuner->RF_IN >= 43000000 && Tuner->RF_IN < 174000000) + if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 174000000 && Tuner->RF_IN < 250000000) + if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 250000000 && Tuner->RF_IN < 350000000) + if (state->RF_IN >= 250000000 && state->RF_IN < 350000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } - if (Tuner->RF_IN >= 350000000 && Tuner->RF_IN < 400000000) + if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 400000000 && Tuner->RF_IN < 570000000) + if (state->RF_IN >= 400000000 && state->RF_IN < 570000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 570000000 && Tuner->RF_IN < 770000000) + if (state->RF_IN >= 570000000 && state->RF_IN < 770000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 0) ; // Bank3 On + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On } - if (Tuner->RF_IN >= 770000000 && Tuner->RF_IN <= 900000000) + if (state->RF_IN >= 770000000 && state->RF_IN <= 900000000) { - status += MXL_ControlWrite(Tuner, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(Tuner, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(Tuner, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(Tuner, 3, 1) ; // Bank3 Off + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On + status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off + status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off + status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off } } } return status ; } -u16 MXL_SetGPIO(Tuner_struct *Tuner, u8 GPIO_Num, u8 GPIO_Val) +// DONE +u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val) { - u16 status = 0 ; + struct mxl5005s_state *state = fe->demodulator_priv; + u16 status = 0; if (GPIO_Num == 1) - status += MXL_ControlWrite(Tuner, GPIO_1B, GPIO_Val ? 0 : 1) ; - // GPIO2 is not available - if (GPIO_Num == 3) - { + status += MXL_ControlWrite(fe, GPIO_1B, GPIO_Val ? 0 : 1); + + /* GPIO2 is not available */ + + if (GPIO_Num == 3) { if (GPIO_Val == 1) { - status += MXL_ControlWrite(Tuner, GPIO_3, 0) ; - status += MXL_ControlWrite(Tuner, GPIO_3B, 0) ; + status += MXL_ControlWrite(fe, GPIO_3, 0); + status += MXL_ControlWrite(fe, GPIO_3B, 0); } if (GPIO_Val == 0) { - status += MXL_ControlWrite(Tuner, GPIO_3, 1) ; - status += MXL_ControlWrite(Tuner, GPIO_3B, 1) ; + status += MXL_ControlWrite(fe, GPIO_3, 1); + status += MXL_ControlWrite(fe, GPIO_3B, 1); } - if (GPIO_Val == 3) { // tri-state - status += MXL_ControlWrite(Tuner, GPIO_3, 0) ; - status += MXL_ControlWrite(Tuner, GPIO_3B, 1) ; + if (GPIO_Val == 3) { /* tri-state */ + status += MXL_ControlWrite(fe, GPIO_3, 0); + status += MXL_ControlWrite(fe, GPIO_3B, 1); } } - if (GPIO_Num == 4) - { + if (GPIO_Num == 4) { if (GPIO_Val == 1) { - status += MXL_ControlWrite(Tuner, GPIO_4, 0) ; - status += MXL_ControlWrite(Tuner, GPIO_4B, 0) ; + status += MXL_ControlWrite(fe, GPIO_4, 0); + status += MXL_ControlWrite(fe, GPIO_4B, 0); } if (GPIO_Val == 0) { - status += MXL_ControlWrite(Tuner, GPIO_4, 1) ; - status += MXL_ControlWrite(Tuner, GPIO_4B, 1) ; + status += MXL_ControlWrite(fe, GPIO_4, 1); + status += MXL_ControlWrite(fe, GPIO_4B, 1); } - if (GPIO_Val == 3) { // tri-state - status += MXL_ControlWrite(Tuner, GPIO_4, 0) ; - status += MXL_ControlWrite(Tuner, GPIO_4B, 1) ; + if (GPIO_Val == 3) { /* tri-state */ + status += MXL_ControlWrite(fe, GPIO_4, 0); + status += MXL_ControlWrite(fe, GPIO_4B, 1); } } - return status ; + return status; } /////////////////////////////////////////////////////////////////////////////// @@ -3907,17 +3732,19 @@ u16 MXL_SetGPIO(Tuner_struct *Tuner, u8 GPIO_Num, u8 GPIO_Val) // >0 : Value exceed maximum allowed for control number // // // /////////////////////////////////////////////////////////////////////////////// -u16 MXL_ControlWrite(Tuner_struct *Tuner, u16 ControlNum, u32 value) +// DONE +u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value) { - u16 status = 0 ; - // Will write ALL Matching Control Name - status += MXL_ControlWrite_Group( Tuner, ControlNum, value, 1 ) ; // Write Matching INIT Control - status += MXL_ControlWrite_Group( Tuner, ControlNum, value, 2 ) ; // Write Matching CH Control + struct mxl5005s_state *state = fe->demodulator_priv; + u16 status = 0; + + /* Will write ALL Matching Control Name */ + status += MXL_ControlWrite_Group(fe, ControlNum, value, 1); /* Write Matching INIT Control * + status += MXL_ControlWrite_Group(fe, ControlNum, value, 2); /* Write Matching CH Control * #ifdef _MXL_INTERNAL - status += MXL_ControlWrite_Group( Tuner, ControlNum, value, 3 ) ; // Write Matching MXL Control + status += MXL_ControlWrite_Group(fe, ControlNum, value, 3); /* Write Matching MXL Control * #endif - - return status ; + return status; } /////////////////////////////////////////////////////////////////////////////// @@ -3947,105 +3774,86 @@ u16 MXL_ControlWrite(Tuner_struct *Tuner, u16 ControlNum, u32 value) // 2 : Control name not found // // // /////////////////////////////////////////////////////////////////////////////// -u16 MXL_ControlWrite_Group(Tuner_struct *Tuner, u16 controlNum, u32 value, u16 controlGroup) +// DONE +u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u16 controlGroup) { - u16 i, j, k ; - u32 highLimit ; - u32 ctrlVal ; + struct mxl5005s_state *state = fe->demodulator_priv; + u16 i, j, k; + u32 highLimit; + u32 ctrlVal; - if( controlGroup == 1) // Initial Control - { - for (i=0; iInit_Ctrl_Num ; i++) - { - if ( controlNum == Tuner->Init_Ctrl[i].Ctrl_Num ) - { // find the control Name - highLimit = 1 << Tuner->Init_Ctrl[i].size ; - if ( value < highLimit) - { - for( j=0; jInit_Ctrl[i].size; j++) - { - Tuner->Init_Ctrl[i].val[j] = (u8)((value >> j) & 0x01) ; - // change the register map accordingly - MXL_RegWriteBit( Tuner, (u8)(Tuner->Init_Ctrl[i].addr[j]), - (u8)(Tuner->Init_Ctrl[i].bit[j]), - (u8)((value>>j) & 0x01) ) ; - } - ctrlVal = 0 ; - for(k=0; kInit_Ctrl[i].size; k++) - { - ctrlVal += Tuner->Init_Ctrl[i].val[k] * (1 << k) ; + if (controlGroup == 1) /* Initial Control */ { + + for (i = 0; i < state->Init_Ctrl_Num; i++) { + + if (controlNum == state->Init_Ctrl[i].Ctrl_Num) { + + highLimit = 1 << state->Init_Ctrl[i].size; + if (value < highLimit) { + for (j = 0; j < state->Init_Ctrl[i].size; j++) { + state->Init_Ctrl[i].val[j] = (u8)((value >> j) & 0x01); + MXL_RegWriteBit(fe, (u8)(state->Init_Ctrl[i].addr[j]), + (u8)(state->Init_Ctrl[i].bit[j]), + (u8)((value>>j) & 0x01) ); } + ctrlVal = 0; + for (k = 0; k < state->Init_Ctrl[i].size; k++) + ctrlVal += state->Init_Ctrl[i].val[k] * (1 << k); } else - { - return -1 ; - } + return -1; } } } - if ( controlGroup == 2) // Chan change Control - { - for (i=0; iCH_Ctrl_Num; i++) - { - if ( controlNum == Tuner->CH_Ctrl[i].Ctrl_Num ) - { // find the control Name - highLimit = 1 << Tuner->CH_Ctrl[i].size ; - if ( value < highLimit) - { - for( j=0; jCH_Ctrl[i].size; j++) - { - Tuner->CH_Ctrl[i].val[j] = (u8)((value >> j) & 0x01) ; - // change the register map accordingly - MXL_RegWriteBit( Tuner, (u8)(Tuner->CH_Ctrl[i].addr[j]), - (u8)(Tuner->CH_Ctrl[i].bit[j]), - (u8)((value>>j) & 0x01) ) ; - } - ctrlVal = 0 ; - for(k=0; kCH_Ctrl[i].size; k++) - { - ctrlVal += Tuner->CH_Ctrl[i].val[k] * (1 << k) ; + if (controlGroup == 2) /* Chan change Control */ { + + for (i = 0; i < state->CH_Ctrl_Num; i++) { + + if (controlNum == state->CH_Ctrl[i].Ctrl_Num ) { + + highLimit = 1 << state->CH_Ctrl[i].size; + if (value < highLimit) { + for (j = 0; j < state->CH_Ctrl[i].size; j++) { + state->CH_Ctrl[i].val[j] = (u8)((value >> j) & 0x01); + MXL_RegWriteBit(fe, (u8)(state->CH_Ctrl[i].addr[j]), + (u8)(state->CH_Ctrl[i].bit[j]), + (u8)((value>>j) & 0x01) ); } + ctrlVal = 0; + for (k = 0; k < state->CH_Ctrl[i].size; k++) + ctrlVal += state->CH_Ctrl[i].val[k] * (1 << k); } else - { - return -1 ; - } + return -1; } } } #ifdef _MXL_INTERNAL - if ( controlGroup == 3) // Maxlinear Control - { - for (i=0; iMXL_Ctrl_Num; i++) - { - if ( controlNum == Tuner->MXL_Ctrl[i].Ctrl_Num ) - { // find the control Name - highLimit = (1 << Tuner->MXL_Ctrl[i].size) ; - if ( value < highLimit) - { - for( j=0; jMXL_Ctrl[i].size; j++) - { - Tuner->MXL_Ctrl[i].val[j] = (u8)((value >> j) & 0x01) ; - // change the register map accordingly - MXL_RegWriteBit( Tuner, (u8)(Tuner->MXL_Ctrl[i].addr[j]), - (u8)(Tuner->MXL_Ctrl[i].bit[j]), - (u8)((value>>j) & 0x01) ) ; - } - ctrlVal = 0 ; - for(k=0; kMXL_Ctrl[i].size; k++) - { - ctrlVal += Tuner->MXL_Ctrl[i].val[k] * (1 << k) ; + if (controlGroup == 3) /* Maxlinear Control */ { + + for (i = 0; i < state->MXL_Ctrl_Num; i++) { + + if (controlNum == state->MXL_Ctrl[i].Ctrl_Num ) { + + highLimit = (1 << state->MXL_Ctrl[i].size) ; + if (value < highLimit) { + for (j = 0; j < state->MXL_Ctrl[i].size; j++) { + state->MXL_Ctrl[i].val[j] = (u8)((value >> j) & 0x01); + MXL_RegWriteBit(fe, (u8)(state->MXL_Ctrl[i].addr[j]), + (u8)(state->MXL_Ctrl[i].bit[j]), + (u8)((value>>j) & 0x01) ); } + ctrlVal = 0; + for(k = 0; k < state->MXL_Ctrl[i].size; k++) + ctrlVal += state->MXL_Ctrl[i].val[k] * (1 << k); } else - { - return -1 ; - } + return -1; } } } #endif - return 0 ; // successful return + return 0 ; /* successful return */ } /////////////////////////////////////////////////////////////////////////////// @@ -4073,20 +3881,20 @@ u16 MXL_ControlWrite_Group(Tuner_struct *Tuner, u16 controlNum, u32 value, u16 c // -1 : Invalid Register Address // // // /////////////////////////////////////////////////////////////////////////////// -u16 MXL_RegWrite(Tuner_struct *Tuner, u8 RegNum, u8 RegVal) +// DONE +u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) { + struct mxl5005s_state *state = fe->demodulator_priv; int i ; - for (i=0; i<104; i++) - { - if (RegNum == Tuner->TunerRegs[i].Reg_Num ) - { - Tuner->TunerRegs[i].Reg_Val = RegVal ; - return 0 ; + for (i = 0; i < 104; i++) { + if (RegNum == state->TunerRegs[i].Reg_Num) { + state->TunerRegs[i].Reg_Val = RegVal; + return 0; } } - return 1 ; + return 1; } /////////////////////////////////////////////////////////////////////////////// @@ -4113,20 +3921,20 @@ u16 MXL_RegWrite(Tuner_struct *Tuner, u8 RegNum, u8 RegVal) // -1 : Invalid Register Address // // // /////////////////////////////////////////////////////////////////////////////// -u16 MXL_RegRead(Tuner_struct *Tuner, u8 RegNum, u8 *RegVal) +// DONE +u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) { + struct mxl5005s_state *state = fe->demodulator_priv; int i ; - for (i=0; i<104; i++) - { - if (RegNum == Tuner->TunerRegs[i].Reg_Num ) - { - *RegVal = (u8)(Tuner->TunerRegs[i].Reg_Val) ; - return 0 ; + for (i = 0; i < 104; i++) { + if (RegNum == state->TunerRegs[i].Reg_Num ) { + *RegVal = (u8)(state->TunerRegs[i].Reg_Val); + return 0; } } - return 1 ; + return 1; } /////////////////////////////////////////////////////////////////////////////// @@ -4150,48 +3958,53 @@ u16 MXL_RegRead(Tuner_struct *Tuner, u8 RegNum, u8 *RegVal) // -1 : Invalid control name // // // /////////////////////////////////////////////////////////////////////////////// -u16 MXL_ControlRead(Tuner_struct *Tuner, u16 controlNum, u32 * value) +// DONE +u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 * value) { + struct mxl5005s_state *state = fe->demodulator_priv; u32 ctrlVal ; u16 i, k ; - for (i=0; iInit_Ctrl_Num ; i++) - { - if ( controlNum == Tuner->Init_Ctrl[i].Ctrl_Num ) - { - ctrlVal = 0 ; - for(k=0; kInit_Ctrl[i].size; k++) - ctrlVal += Tuner->Init_Ctrl[i].val[k] * (1 << k) ; - *value = ctrlVal ; - return 0 ; + for (i = 0; i < state->Init_Ctrl_Num ; i++) { + + if (controlNum == state->Init_Ctrl[i].Ctrl_Num) { + + ctrlVal = 0; + for (k = 0; k < state->Init_Ctrl[i].size; k++) + ctrlVal += state->Init_Ctrl[i].val[k] * (1 << k); + *value = ctrlVal; + return 0; } } - for (i=0; iCH_Ctrl_Num ; i++) - { - if ( controlNum == Tuner->CH_Ctrl[i].Ctrl_Num ) - { - ctrlVal = 0 ; - for(k=0; kCH_Ctrl[i].size; k++) - ctrlVal += Tuner->CH_Ctrl[i].val[k] * (1 << k) ; - *value = ctrlVal ; - return 0 ; + + for (i = 0; i < state->CH_Ctrl_Num ; i++) { + + if (controlNum == state->CH_Ctrl[i].Ctrl_Num) { + + ctrlVal = 0; + for (k = 0; k < state->CH_Ctrl[i].size; k++) + ctrlVal += state->CH_Ctrl[i].val[k] * (1 << k); + *value = ctrlVal; + return 0; + } } #ifdef _MXL_INTERNAL - for (i=0; iMXL_Ctrl_Num ; i++) - { - if ( controlNum == Tuner->MXL_Ctrl[i].Ctrl_Num ) - { - ctrlVal = 0 ; - for(k=0; kMXL_Ctrl[i].size; k++) - ctrlVal += Tuner->MXL_Ctrl[i].val[k] * (1<MXL_Ctrl_Num ; i++) { + + if (controlNum == state->MXL_Ctrl[i].Ctrl_Num) { + + ctrlVal = 0; + for (k = 0; k < state->MXL_Ctrl[i].size; k++) + ctrlVal += state->MXL_Ctrl[i].val[k] * (1<demodulator_priv; u16 i, j, k ; u16 Count ; - for (i=0; iInit_Ctrl_Num ; i++) - { - if ( controlNum == Tuner->Init_Ctrl[i].Ctrl_Num ) - { - Count = 1 ; - RegNum[0] = (u8)(Tuner->Init_Ctrl[i].addr[0]) ; + for (i = 0; i < state->Init_Ctrl_Num ; i++) { + + if ( controlNum == state->Init_Ctrl[i].Ctrl_Num ) { + + Count = 1; + RegNum[0] = (u8)(state->Init_Ctrl[i].addr[0]); + + for (k = 1; k < state->Init_Ctrl[i].size; k++) { + + for (j = 0; j < Count; j++) { + + if (state->Init_Ctrl[i].addr[k] != RegNum[j]) { + + Count ++; + RegNum[Count-1] = (u8)(state->Init_Ctrl[i].addr[k]); - for(k=1; kInit_Ctrl[i].size; k++) - { - for (j= 0; jInit_Ctrl[i].addr[k] != RegNum[j]) - { - Count ++ ; - RegNum[Count-1] = (u8)(Tuner->Init_Ctrl[i].addr[k]) ; } } } - *count = Count ; - return 0 ; + *count = Count; + return 0; } } - for (i=0; iCH_Ctrl_Num ; i++) - { - if ( controlNum == Tuner->CH_Ctrl[i].Ctrl_Num ) - { - Count = 1 ; - RegNum[0] = (u8)(Tuner->CH_Ctrl[i].addr[0]) ; + for (i = 0; i < state->CH_Ctrl_Num ; i++) { + + if ( controlNum == state->CH_Ctrl[i].Ctrl_Num ) { + + Count = 1; + RegNum[0] = (u8)(state->CH_Ctrl[i].addr[0]); + + for (k = 1; k < state->CH_Ctrl[i].size; k++) { + + for (j= 0; jCH_Ctrl[i].addr[k] != RegNum[j]) { + + Count ++; + RegNum[Count-1] = (u8)(state->CH_Ctrl[i].addr[k]); - for(k=1; kCH_Ctrl[i].size; k++) - { - for (j= 0; jCH_Ctrl[i].addr[k] != RegNum[j]) - { - Count ++ ; - RegNum[Count-1] = (u8)(Tuner->CH_Ctrl[i].addr[k]) ; } } } - *count = Count ; - return 0 ; + *count = Count; + return 0; } } #ifdef _MXL_INTERNAL - for (i=0; iMXL_Ctrl_Num ; i++) - { - if ( controlNum == Tuner->MXL_Ctrl[i].Ctrl_Num ) - { - Count = 1 ; - RegNum[0] = (u8)(Tuner->MXL_Ctrl[i].addr[0]) ; + for (i = 0; i < state->MXL_Ctrl_Num ; i++) { + + if ( controlNum == state->MXL_Ctrl[i].Ctrl_Num ) { + + Count = 1; + RegNum[0] = (u8)(state->MXL_Ctrl[i].addr[0]); + + for (k = 1; k < state->MXL_Ctrl[i].size; k++) { + + for (j = 0; jMXL_Ctrl[i].addr[k] != RegNum[j]) { + + Count ++; + RegNum[Count-1] = (u8)state->MXL_Ctrl[i].addr[k]; - for(k=1; kMXL_Ctrl[i].size; k++) - { - for (j= 0; jMXL_Ctrl[i].addr[k] != RegNum[j]) - { - Count ++ ; - RegNum[Count-1] = (u8)Tuner->MXL_Ctrl[i].addr[k] ; } } } - *count = Count ; - return 0 ; + *count = Count; + return 0; } } #endif - *count = 0 ; - return 1 ; + *count = 0; + return 1; } /////////////////////////////////////////////////////////////////////////////// @@ -4308,7 +4126,7 @@ u16 MXL_ControlRegRead(Tuner_struct *Tuner, u16 controlNum, u8 *RegNum, int * co // Inputs: // // Tuner_struct : structure defined at higher level // // address : register address // -// bit : register bit number // +// bit : register bit number // // bitVal : register bit value // // // // Outputs: // @@ -4318,12 +4136,12 @@ u16 MXL_ControlRegRead(Tuner_struct *Tuner, u16 controlNum, u8 *RegNum, int * co // NONE // // // /////////////////////////////////////////////////////////////////////////////// - -void MXL_RegWriteBit(Tuner_struct *Tuner, u8 address, u8 bit, u8 bitVal) +// DONE +void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal) { + struct mxl5005s_state *state = fe->demodulator_priv; int i ; - // Declare Local Constants const u8 AND_MAP[8] = { 0xFE, 0xFD, 0xFB, 0xF7, 0xEF, 0xDF, 0xBF, 0x7F } ; @@ -4332,17 +4150,16 @@ void MXL_RegWriteBit(Tuner_struct *Tuner, u8 address, u8 bit, u8 bitVal) 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 } ; - for(i=0; iTunerRegs_Num; i++) { - if ( Tuner->TunerRegs[i].Reg_Num == address ) { + for (i = 0; i < state->TunerRegs_Num; i++) { + if (state->TunerRegs[i].Reg_Num == address) { if (bitVal) - Tuner->TunerRegs[i].Reg_Val |= OR_MAP[bit] ; + state->TunerRegs[i].Reg_Val |= OR_MAP[bit]; else - Tuner->TunerRegs[i].Reg_Val &= AND_MAP[bit] ; + state->TunerRegs[i].Reg_Val &= AND_MAP[bit]; break ; } } -} ; - +} /////////////////////////////////////////////////////////////////////////////// // // @@ -4367,37 +4184,43 @@ void MXL_RegWriteBit(Tuner_struct *Tuner, u8 address, u8 bit, u8 bitVal) // Computed value // // // /////////////////////////////////////////////////////////////////////////////// -u32 MXL_Ceiling( u32 value, u32 resolution ) +// DONE +u32 MXL_Ceiling(u32 value, u32 resolution) { - return (value/resolution + (value%resolution > 0 ? 1 : 0)) ; -}; + return (value/resolution + (value % resolution > 0 ? 1 : 0)); +} // // Retrieve the Initialzation Registers // -u16 MXL_GetInitRegister(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count) +// DONE +u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { + struct mxl5005s_state *state = fe->demodulator_priv; u16 status = 0; int i ; - u8 RegAddr[] = {11, 12, 13, 22, 32, 43, 44, 53, 56, 59, 73, - 76, 77, 91, 134, 135, 137, 147, - 156, 166, 167, 168, 25 } ; - *count = sizeof(RegAddr) / sizeof(u8) ; + u8 RegAddr[] = { + 11, 12, 13, 22, 32, 43, 44, 53, 56, 59, 73, + 76, 77, 91, 134, 135, 137, 147, + 156, 166, 167, 168, 25 }; - status += MXL_BlockInit(Tuner) ; + *count = sizeof(RegAddr) / sizeof(u8); - for (i=0 ; i< *count; i++) - { - RegNum[i] = RegAddr[i] ; - status += MXL_RegRead(Tuner, RegNum[i], &RegVal[i]) ; + status += MXL_BlockInit(fe); + + for (i = 0 ; i < *count; i++) { + RegNum[i] = RegAddr[i]; + status += MXL_RegRead(fe, RegNum[i], &RegVal[i]); } - return status ; + return status; } -u16 MXL_GetCHRegister(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count) +// DONE +u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { + struct mxl5005s_state *state = fe->demodulator_priv; u16 status = 0; int i ; @@ -4413,203 +4236,207 @@ u16 MXL_GetCHRegister(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count) // RegAddr[i] = i; #endif - *count = sizeof(RegAddr) / sizeof(u8) ; + *count = sizeof(RegAddr) / sizeof(u8); - for (i=0 ; i< *count; i++) - { - RegNum[i] = RegAddr[i] ; - status += MXL_RegRead(Tuner, RegNum[i], &RegVal[i]) ; + for (i = 0 ; i < *count; i++) { + RegNum[i] = RegAddr[i]; + status += MXL_RegRead(fe, RegNum[i], &RegVal[i]); } - return status ; - + return status; } -u16 MXL_GetCHRegister_ZeroIF(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count) +// DONE +u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { - u16 status = 0 ; - int i ; + struct mxl5005s_state *state = fe->demodulator_priv; + u16 status = 0; + int i; - u8 RegAddr[] = {43, 136} ; + u8 RegAddr[] = {43, 136}; - *count = sizeof(RegAddr) / sizeof(u8) ; + *count = sizeof(RegAddr) / sizeof(u8); - for (i=0; i<*count; i++) - { - RegNum[i] = RegAddr[i] ; - status += MXL_RegRead(Tuner, RegNum[i], &RegVal[i]) ; + for (i = 0; i < *count; i++) { + RegNum[i] = RegAddr[i]; + status += MXL_RegRead(fe, RegNum[i], &RegVal[i]); } - return status ; + return status; } -u16 MXL_GetCHRegister_LowIF(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count) +// DONE +u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { - u16 status = 0 ; - int i ; + struct mxl5005s_state *state = fe->demodulator_priv; + u16 status = 0; + int i; - u8 RegAddr[] = {138} ; + u8 RegAddr[] = { 138 }; - *count = sizeof(RegAddr) / sizeof(u8) ; + *count = sizeof(RegAddr) / sizeof(u8); - for (i=0; i<*count; i++) - { - RegNum[i] = RegAddr[i] ; - status += MXL_RegRead(Tuner, RegNum[i], &RegVal[i]) ; + for (i = 0; i < *count; i++) { + RegNum[i] = RegAddr[i]; + status += MXL_RegRead(fe, RegNum[i], &RegVal[i]); } - return status ; + return status; } +// DONE u16 MXL_GetMasterControl(u8 *MasterReg, int state) { - if (state == 1) // Load_Start - *MasterReg = 0xF3 ; - if (state == 2) // Power_Down - *MasterReg = 0x41 ; - if (state == 3) // Synth_Reset - *MasterReg = 0xB1 ; - if (state == 4) // Seq_Off - *MasterReg = 0xF1 ; - - return 0 ; + if (state == 1) /* Load_Start */ + *MasterReg = 0xF3; + if (state == 2) /* Power_Down */ + *MasterReg = 0x41; + if (state == 3) /* Synth_Reset */ + *MasterReg = 0xB1; + if (state == 4) /* Seq_Off */ + *MasterReg = 0xF1; + + return 0; } #ifdef _MXL_PRODUCTION -u16 MXL_VCORange_Test(Tuner_struct *Tuner, int VCO_Range) +u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range) { + struct mxl5005s_state *state = fe->demodulator_priv; u16 status = 0 ; if (VCO_Range == 1) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1); - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0); - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0); - status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1); - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1); - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1); - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0); - if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1); - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8); - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 56); - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 180224); - } - if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 56 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 222822 ) ; - } - if (Tuner->Mode == 1) // Digital Mode { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1 ) ; - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 56 ) ; - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 229376 ) ; + status += MXL_ControlWrite(fe, RFSYN_EN_DIV, 1); + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(fe, RFSYN_DIVM, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0); + if (state->Mode == 0 && state->IF_Mode == 1) /* Analog Low IF Mode */ { + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 56); + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 180224); + } + if (state->Mode == 0 && state->IF_Mode == 0) /* Analog Zero IF Mode */ { + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 56); + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 222822); + } + if (state->Mode == 1) /* Digital Mode */ { + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 56); + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 229376); } } if (VCO_Range == 2) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1); - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0); - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0); - status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1); - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1); - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1); - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0); - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1); - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 41); - if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1); - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42); - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438); - } - if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1); - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42); - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438); - } - if (Tuner->Mode == 1) // Digital Mode { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 1); - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 41); - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 16384); + status += MXL_ControlWrite(fe, RFSYN_EN_DIV, 1); + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(fe, RFSYN_DIVM, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 41); + if (state->Mode == 0 && state->IF_Mode == 1) /* Analog Low IF Mode */ { + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42); + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 206438); + } + if (state->Mode == 0 && state->IF_Mode == 0) /* Analog Zero IF Mode */ { + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42); + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 206438); + } + if (state->Mode == 1) /* Digital Mode */ { + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 41); + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 16384); } } if (VCO_Range == 3) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1); - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0); - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0); - status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1); - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1); - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1); - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0); - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8); - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42); - if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8); - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 44); - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 173670); - } - if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8); - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 44); - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 173670); - } - if (Tuner->Mode == 1) // Digital Mode { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 8); - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 42); - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 245760); + status += MXL_ControlWrite(fe, RFSYN_EN_DIV, 1); + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(fe, RFSYN_DIVM, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42); + if (state->Mode == 0 && state->IF_Mode == 1) /* Analog Low IF Mode */ { + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 44); + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 173670); + } + if (state->Mode == 0 && state->IF_Mode == 0) /* Analog Zero IF Mode */ { + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 44); + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 173670); + } + if (state->Mode == 1) /* Digital Mode */ { + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42); + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 245760); } } if (VCO_Range == 4) { - status += MXL_ControlWrite(Tuner, RFSYN_EN_DIV, 1); - status += MXL_ControlWrite(Tuner, RFSYN_EN_OUTMUX, 0); - status += MXL_ControlWrite(Tuner, RFSYN_SEL_DIVM, 0); - status += MXL_ControlWrite(Tuner, RFSYN_DIVM, 1); - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_OUT, 1); - status += MXL_ControlWrite(Tuner, RFSYN_RF_DIV_BIAS, 1); - status += MXL_ControlWrite(Tuner, DN_SEL_FREQ, 0); - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27); - if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF Mode { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27); - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438); - } - if (Tuner->Mode == 0 && Tuner->IF_Mode == 0) // Analog Zero IF Mode { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27); - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 206438); - } - if (Tuner->Mode == 1) // Digital Mode { - status += MXL_ControlWrite(Tuner, RFSYN_SEL_VCO_HI, 0); - status += MXL_ControlWrite(Tuner, RFSYN_VCO_BIAS, 40); - status += MXL_ControlWrite(Tuner, CHCAL_INT_MOD_RF, 27); - status += MXL_ControlWrite(Tuner, CHCAL_FRAC_MOD_RF, 212992); + status += MXL_ControlWrite(fe, RFSYN_EN_DIV, 1); + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(fe, RFSYN_DIVM, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27); + if (state->Mode == 0 && state->IF_Mode == 1) /* Analog Low IF Mode */ { + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27); + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 206438); + } + if (state->Mode == 0 && state->IF_Mode == 0) /* Analog Zero IF Mode */ { + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27); + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 206438); + } + if (state->Mode == 1) /* Digital Mode */ { + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27); + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 212992); } } return status; } -u16 MXL_Hystersis_Test(Tuner_struct *Tuner, int Hystersis) +// DONE +u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis) { + struct mxl5005s_state *state = fe->demodulator_priv; u16 status = 0; if (Hystersis == 1) - status += MXL_ControlWrite(Tuner, DN_BYPASS_AGC_I2C, 1); + status += MXL_ControlWrite(fe, DN_BYPASS_AGC_I2C, 1); return status; } diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h index 1944d9e..df49826 100644 --- a/drivers/media/common/tuners/mxl5005s.h +++ b/drivers/media/common/tuners/mxl5005s.h @@ -140,61 +140,6 @@ typedef struct _TunerReg_struct u16 Reg_Val; /* Current sofware programmed value waiting to be writen */ } TunerReg_struct; -/* MXL5005 Tuner Control Struct */ -typedef struct _TunerControl_struct { - u16 Ctrl_Num; /* Control Number */ - u16 size; /* Number of bits to represent Value */ - u16 addr[25]; /* Array of Tuner Register Address for each bit position */ - u16 bit[25]; /* Array of bit position in Register Address for each bit position */ - u16 val[25]; /* Binary representation of Value */ -} TunerControl_struct; - -/* MXL5005 Tuner Struct */ -typedef struct _Tuner_struct -{ - u8 Mode; /* 0: Analog Mode ; 1: Digital Mode */ - u8 IF_Mode; /* for Analog Mode, 0: zero IF; 1: low IF */ - u32 Chan_Bandwidth; /* filter channel bandwidth (6, 7, 8) */ - u32 IF_OUT; /* Desired IF Out Frequency */ - u16 IF_OUT_LOAD; /* IF Out Load Resistor (200/300 Ohms) */ - u32 RF_IN; /* RF Input Frequency */ - u32 Fxtal; /* XTAL Frequency */ - u8 AGC_Mode; /* AGC Mode 0: Dual AGC; 1: Single AGC */ - u16 TOP; /* Value: take over point */ - u8 CLOCK_OUT; /* 0: turn off clock out; 1: turn on clock out */ - u8 DIV_OUT; /* 4MHz or 16MHz */ - u8 CAPSELECT; /* 0: disable On-Chip pulling cap; 1: enable */ - u8 EN_RSSI; /* 0: disable RSSI; 1: enable RSSI */ - u8 Mod_Type; /* Modulation Type; */ - /* 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable */ - u8 TF_Type; /* Tracking Filter Type */ - /* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */ - - /* Calculated Settings */ - u32 RF_LO; /* Synth RF LO Frequency */ - u32 IF_LO; /* Synth IF LO Frequency */ - u32 TG_LO; /* Synth TG_LO Frequency */ - - /* Pointers to ControlName Arrays */ - u16 Init_Ctrl_Num; /* Number of INIT Control Names */ - TunerControl_struct - Init_Ctrl[INITCTRL_NUM]; /* INIT Control Names Array Pointer */ - - u16 CH_Ctrl_Num; /* Number of CH Control Names */ - TunerControl_struct - CH_Ctrl[CHCTRL_NUM]; /* CH Control Name Array Pointer */ - - u16 MXL_Ctrl_Num; /* Number of MXL Control Names */ - TunerControl_struct - MXL_Ctrl[MXLCTRL_NUM]; /* MXL Control Name Array Pointer */ - - /* Pointer to Tuner Register Array */ - u16 TunerRegs_Num; /* Number of Tuner Registers */ - TunerReg_struct - TunerRegs[TUNER_REGS_NUM]; /* Tuner Register Array Pointer */ - -} Tuner_struct; - typedef enum { /* Initialization Control Names */ @@ -290,60 +235,6 @@ typedef enum * MaxLinear source code - Common_MXL.h (?) */ -void InitTunerControls(Tuner_struct *Tuner); -u16 MXL_BlockInit(Tuner_struct *Tuner); -u16 MXL5005_RegisterInit(Tuner_struct *Tuner); -u16 MXL5005_ControlInit(Tuner_struct *Tuner); -#ifdef _MXL_INTERNAL -u16 MXL5005_MXLControlInit(Tuner_struct *Tuner); -#endif - -u16 MXL5005_TunerConfig(Tuner_struct *Tuner, - u8 Mode, /* 0: Analog Mode ; 1: Digital Mode */ - u8 IF_mode, /* for Analog Mode, 0: zero IF; 1: low IF */ - u32 Bandwidth, /* filter channel bandwidth (6, 7, 8) */ - u32 IF_out, /* Desired IF Out Frequency */ - u32 Fxtal, /* XTAL Frequency */ - u8 AGC_Mode, /* AGC Mode - Dual AGC: 0, Single AGC: 1 */ - u16 TOP, /* 0: Dual AGC; Value: take over point */ - u16 IF_OUT_LOAD, /* IF Out Load Resistor (200 / 300 Ohms) */ - u8 CLOCK_OUT, /* 0: turn off clock out; 1: turn on clock out */ - u8 DIV_OUT, /* 4MHz or 16MHz */ - u8 CAPSELECT, /* 0: disable On-Chip pulling cap; 1: enable */ - u8 EN_RSSI, /* 0: disable RSSI; 1: enable RSSI */ - u8 Mod_Type, /* Modulation Type; */ - /* 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable */ - u8 TF_Type /* Tracking Filter Type */ - /* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */ - ); - -void MXL_SynthIFLO_Calc(Tuner_struct *Tuner); -void MXL_SynthRFTGLO_Calc(Tuner_struct *Tuner); -u16 MXL_RegWrite(Tuner_struct *Tuner, u8 RegNum, u8 RegVal); -u16 MXL_RegRead(Tuner_struct *Tuner, u8 RegNum, u8 *RegVal); -u16 MXL_ControlWrite(Tuner_struct *Tuner, u16 ControlNum, u32 value); -u16 MXL_ControlWrite_Group(Tuner_struct *Tuner, u16 ControlNum, u32 value, u16 controlGroup); -u16 MXL_ControlRead(Tuner_struct *Tuner, u16 ControlNum, u32 * value); -u16 MXL_ControlRegRead(Tuner_struct *Tuner, u16 ControlNum, u8 *RegNum, int *count); -void MXL_RegWriteBit(Tuner_struct *Tuner, u8 address, u8 bit, u8 bitVal); -u16 MXL_IFSynthInit(Tuner_struct * Tuner ); -u16 MXL_TuneRF(Tuner_struct *Tuner, u32 RF_Freq); -u16 MXL_OverwriteICDefault(Tuner_struct *Tuner); -u16 MXL_SetGPIO(Tuner_struct *Tuner, u8 GPIO_Num, u8 GPIO_Val); -u32 MXL_Ceiling(u32 value, u32 resolution); -u32 MXL_GetXtalInt(u32 Xtal_Freq); - -u16 MXL_GetInitRegister(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count); -u16 MXL_GetCHRegister(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count); -u16 MXL_GetCHRegister_ZeroIF(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count); -u16 MXL_GetCHRegister_LowIF(Tuner_struct *Tuner, u8 * RegNum, u8 *RegVal, int *count); -u16 MXL_GetMasterControl(u8 *MasterReg, int state); - -#ifdef _MXL_PRODUCTION -u16 MXL_VCORange_Test(Tuner_struct *Tuner, int VCO_Range); -u16 MXL_Hystersis_Test(Tuner_struct *Tuner, int Hystersis); -#endif - /* Constants */ #define MXL5005S_REG_WRITING_TABLE_LEN_MAX 104 #define MXL5005S_LATCH_BYTE 0xfe @@ -401,62 +292,6 @@ enum MXL5005S_IF_OUTPUT_LOAD_300_OHM = 300, }; -/* MxL5005S extra module alias */ -typedef struct MXL5005S_EXTRA_MODULE_TAG MXL5005S_EXTRA_MODULE; - -/* MxL5005S register setting function pointer */ -typedef int -(*MXL5005S_FP_SET_REGS_WITH_TABLE)( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - unsigned char *pAddrTable, - unsigned char *pByteTable, - int TableLen - ); - - -/* MxL5005S register mask bits setting function pointer */ -typedef int -(*MXL5005S_FP_SET_REG_MASK_BITS)( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - unsigned char RegAddr, - unsigned char Msb, - unsigned char Lsb, - const unsigned char WritingValue - ); - -/* MxL5005S spectrum mode setting function pointer */ -typedef int -(*MXL5005S_FP_SET_SPECTRUM_MODE)( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - int SpectrumMode - ); - -/* MxL5005S bandwidth setting function pointer */ -typedef int -(*MXL5005S_FP_SET_BANDWIDTH_HZ)( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - unsigned long BandwidthHz - ); - -/* MxL5005S extra module */ -struct MXL5005S_EXTRA_MODULE_TAG -{ - /* MxL5005S function pointers */ - MXL5005S_FP_SET_REGS_WITH_TABLE SetRegsWithTable; - MXL5005S_FP_SET_REG_MASK_BITS SetRegMaskBits; - MXL5005S_FP_SET_SPECTRUM_MODE SetSpectrumMode; - MXL5005S_FP_SET_BANDWIDTH_HZ SetBandwidthHz; - - /* MxL5005S extra data */ - unsigned char AgcMasterByte; /* Variable name in MaxLinear source code: AGC_MASTER_BYTE */ - - /* MaxLinear defined struct */ - Tuner_struct MxlDefinedTunerStructure; -}; /* End of common_mxl.h (?) */ #endif /* __MXL5005S_H */ -- cgit v1.1 From 85d220d03b70180b9958b29d43e99c7135f00654 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 1 May 2008 05:48:14 -0300 Subject: V4L/DVB (7867): mxl5005s: Cleanup #4 Cleanup #4 Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 926 +++++++++++++++++++++------------ drivers/media/common/tuners/mxl5005s.h | 291 ++--------- 2 files changed, 636 insertions(+), 581 deletions(-) diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index d888548..7e68717 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -24,6 +24,270 @@ #include "mxl5005s.h" +static int debug; + +#define dprintk(level, arg...) do { \ + if (debug >= level) \ + printk(arg); \ + } while (0) + +#define TUNER_REGS_NUM 104 +#define INITCTRL_NUM 40 + +#ifdef _MXL_PRODUCTION +#define CHCTRL_NUM 39 +#else +#define CHCTRL_NUM 36 +#endif + +#define MXLCTRL_NUM 189 +#define MASTER_CONTROL_ADDR 9 + +/* Enumeration of AGC Mode */ +typedef enum +{ + MXL_DUAL_AGC = 0, + MXL_SINGLE_AGC +} AGC_Mode; + +/* Enumeration of Master Control Register State */ +typedef enum +{ + MC_LOAD_START = 1, + MC_POWER_DOWN, + MC_SYNTH_RESET, + MC_SEQ_OFF +} Master_Control_State; + +/* Enumeration of MXL5005 Tuner Mode */ +typedef enum +{ + MXL_ANALOG_MODE = 0, + MXL_DIGITAL_MODE +} Tuner_Mode; + +/* Enumeration of MXL5005 Tuner IF Mode */ +typedef enum +{ + MXL_ZERO_IF = 0, + MXL_LOW_IF +} Tuner_IF_Mode; + +/* Enumeration of MXL5005 Tuner Clock Out Mode */ +typedef enum +{ + MXL_CLOCK_OUT_DISABLE = 0, + MXL_CLOCK_OUT_ENABLE +} Tuner_Clock_Out; + +/* Enumeration of MXL5005 Tuner Div Out Mode */ +typedef enum +{ + MXL_DIV_OUT_1 = 0, + MXL_DIV_OUT_4 + +} Tuner_Div_Out; + +/* Enumeration of MXL5005 Tuner Pull-up Cap Select Mode */ +typedef enum +{ + MXL_CAP_SEL_DISABLE = 0, + MXL_CAP_SEL_ENABLE + +} Tuner_Cap_Select; + +/* Enumeration of MXL5005 Tuner RSSI Mode */ +typedef enum +{ + MXL_RSSI_DISABLE = 0, + MXL_RSSI_ENABLE + +} Tuner_RSSI; + +/* Enumeration of MXL5005 Tuner Modulation Type */ +typedef enum +{ + MXL_DEFAULT_MODULATION = 0, + MXL_DVBT, + MXL_ATSC, + MXL_QAM, + MXL_ANALOG_CABLE, + MXL_ANALOG_OTA +} Tuner_Modu_Type; + +/* Enumeration of MXL5005 Tuner Tracking Filter Type */ +typedef enum +{ + MXL_TF_DEFAULT = 0, + MXL_TF_OFF, + MXL_TF_C, + MXL_TF_C_H, + MXL_TF_D, + MXL_TF_D_L, + MXL_TF_E, + MXL_TF_F, + MXL_TF_E_2, + MXL_TF_E_NA, + MXL_TF_G +} Tuner_TF_Type; + +/* MXL5005 Tuner Register Struct */ +typedef struct _TunerReg_struct +{ + u16 Reg_Num; /* Tuner Register Address */ + u16 Reg_Val; /* Current sofware programmed value waiting to be writen */ +} TunerReg_struct; + +typedef enum +{ + /* Initialization Control Names */ + DN_IQTN_AMP_CUT = 1, /* 1 */ + BB_MODE, /* 2 */ + BB_BUF, /* 3 */ + BB_BUF_OA, /* 4 */ + BB_ALPF_BANDSELECT, /* 5 */ + BB_IQSWAP, /* 6 */ + BB_DLPF_BANDSEL, /* 7 */ + RFSYN_CHP_GAIN, /* 8 */ + RFSYN_EN_CHP_HIGAIN, /* 9 */ + AGC_IF, /* 10 */ + AGC_RF, /* 11 */ + IF_DIVVAL, /* 12 */ + IF_VCO_BIAS, /* 13 */ + CHCAL_INT_MOD_IF, /* 14 */ + CHCAL_FRAC_MOD_IF, /* 15 */ + DRV_RES_SEL, /* 16 */ + I_DRIVER, /* 17 */ + EN_AAF, /* 18 */ + EN_3P, /* 19 */ + EN_AUX_3P, /* 20 */ + SEL_AAF_BAND, /* 21 */ + SEQ_ENCLK16_CLK_OUT, /* 22 */ + SEQ_SEL4_16B, /* 23 */ + XTAL_CAPSELECT, /* 24 */ + IF_SEL_DBL, /* 25 */ + RFSYN_R_DIV, /* 26 */ + SEQ_EXTSYNTHCALIF, /* 27 */ + SEQ_EXTDCCAL, /* 28 */ + AGC_EN_RSSI, /* 29 */ + RFA_ENCLKRFAGC, /* 30 */ + RFA_RSSI_REFH, /* 31 */ + RFA_RSSI_REF, /* 32 */ + RFA_RSSI_REFL, /* 33 */ + RFA_FLR, /* 34 */ + RFA_CEIL, /* 35 */ + SEQ_EXTIQFSMPULSE, /* 36 */ + OVERRIDE_1, /* 37 */ + BB_INITSTATE_DLPF_TUNE, /* 38 */ + TG_R_DIV, /* 39 */ + EN_CHP_LIN_B, /* 40 */ + + /* Channel Change Control Names */ + DN_POLY = 51, /* 51 */ + DN_RFGAIN, /* 52 */ + DN_CAP_RFLPF, /* 53 */ + DN_EN_VHFUHFBAR, /* 54 */ + DN_GAIN_ADJUST, /* 55 */ + DN_IQTNBUF_AMP, /* 56 */ + DN_IQTNGNBFBIAS_BST, /* 57 */ + RFSYN_EN_OUTMUX, /* 58 */ + RFSYN_SEL_VCO_OUT, /* 59 */ + RFSYN_SEL_VCO_HI, /* 60 */ + RFSYN_SEL_DIVM, /* 61 */ + RFSYN_RF_DIV_BIAS, /* 62 */ + DN_SEL_FREQ, /* 63 */ + RFSYN_VCO_BIAS, /* 64 */ + CHCAL_INT_MOD_RF, /* 65 */ + CHCAL_FRAC_MOD_RF, /* 66 */ + RFSYN_LPF_R, /* 67 */ + CHCAL_EN_INT_RF, /* 68 */ + TG_LO_DIVVAL, /* 69 */ + TG_LO_SELVAL, /* 70 */ + TG_DIV_VAL, /* 71 */ + TG_VCO_BIAS, /* 72 */ + SEQ_EXTPOWERUP, /* 73 */ + OVERRIDE_2, /* 74 */ + OVERRIDE_3, /* 75 */ + OVERRIDE_4, /* 76 */ + SEQ_FSM_PULSE, /* 77 */ + GPIO_4B, /* 78 */ + GPIO_3B, /* 79 */ + GPIO_4, /* 80 */ + GPIO_3, /* 81 */ + GPIO_1B, /* 82 */ + DAC_A_ENABLE, /* 83 */ + DAC_B_ENABLE, /* 84 */ + DAC_DIN_A, /* 85 */ + DAC_DIN_B, /* 86 */ +#ifdef _MXL_PRODUCTION + RFSYN_EN_DIV, /* 87 */ + RFSYN_DIVM, /* 88 */ + DN_BYPASS_AGC_I2C /* 89 */ +#endif +} MXL5005_ControlName; + +/* + * The following context is source code provided by MaxLinear. + * MaxLinear source code - Common_MXL.h (?) + */ + +/* Constants */ +#define MXL5005S_REG_WRITING_TABLE_LEN_MAX 104 +#define MXL5005S_LATCH_BYTE 0xfe + +/* Register address, MSB, and LSB */ +#define MXL5005S_BB_IQSWAP_ADDR 59 +#define MXL5005S_BB_IQSWAP_MSB 0 +#define MXL5005S_BB_IQSWAP_LSB 0 + +#define MXL5005S_BB_DLPF_BANDSEL_ADDR 53 +#define MXL5005S_BB_DLPF_BANDSEL_MSB 4 +#define MXL5005S_BB_DLPF_BANDSEL_LSB 3 + +/* Standard modes */ +enum +{ + MXL5005S_STANDARD_DVBT, + MXL5005S_STANDARD_ATSC, +}; +#define MXL5005S_STANDARD_MODE_NUM 2 + +/* Bandwidth modes */ +enum +{ + MXL5005S_BANDWIDTH_6MHZ = 6000000, + MXL5005S_BANDWIDTH_7MHZ = 7000000, + MXL5005S_BANDWIDTH_8MHZ = 8000000, +}; +#define MXL5005S_BANDWIDTH_MODE_NUM 3 + +/* Top modes */ +enum +{ + MXL5005S_TOP_5P5 = 55, + MXL5005S_TOP_7P2 = 72, + MXL5005S_TOP_9P2 = 92, + MXL5005S_TOP_11P0 = 110, + MXL5005S_TOP_12P9 = 129, + MXL5005S_TOP_14P7 = 147, + MXL5005S_TOP_16P8 = 168, + MXL5005S_TOP_19P4 = 194, + MXL5005S_TOP_21P2 = 212, + MXL5005S_TOP_23P2 = 232, + MXL5005S_TOP_25P2 = 252, + MXL5005S_TOP_27P1 = 271, + MXL5005S_TOP_29P2 = 292, + MXL5005S_TOP_31P7 = 317, + MXL5005S_TOP_34P9 = 349, +}; + +/* IF output load */ +enum +{ + MXL5005S_IF_OUTPUT_LOAD_200_OHM = 200, + MXL5005S_IF_OUTPUT_LOAD_300_OHM = 300, +}; + /* MXL5005 Tuner Control Struct */ typedef struct _TunerControl_struct { u16 Ctrl_Num; /* Control Number */ @@ -77,241 +341,138 @@ struct mxl5005s_state TunerReg_struct TunerRegs[TUNER_REGS_NUM]; /* Tuner Register Array Pointer */ -}; - - -int mxl5005s_Initialize( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner - ) -{ - MXL5005S_EXTRA_MODULE *pExtra; - - unsigned char AgcMasterByte; - unsigned char AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; - unsigned char ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; - int TableLen; - - // Get tuner extra module. - pExtra = (MXL5005S_EXTRA_MODULE *)pTuner->pExtra; - - // Get AGC master byte - AgcMasterByte = pExtra->AgcMasterByte; + /* Linux driver framework specific */ + const struct mxl5005s_config *config; - // Initialize MxL5005S tuner according to MxL5005S tuner example code. - - // Tuner initialization stage 0 - MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET); - AddrTable[0] = MASTER_CONTROL_ADDR; - ByteTable[0] |= AgcMasterByte; - - if(pExtra->SetRegsWithTable( dib,pTuner, AddrTable, ByteTable, LEN_1_BYTE) != FUNCTION_SUCCESS) - goto error_status_set_tuner_registers; - - // Tuner initialization stage 1 - MXL_GetInitRegister(&pExtra->MxlDefinedTunerStructure, AddrTable, ByteTable, &TableLen); - - if(pExtra->SetRegsWithTable( dib,pTuner, AddrTable, ByteTable, TableLen) != FUNCTION_SUCCESS) - goto error_status_set_tuner_registers; - - return FUNCTION_SUCCESS; - -error_status_set_tuner_registers: - return FUNCTION_ERROR; -} + struct dvb_frontend *frontend; + struct i2c_adapter *i2c; +}; -int mxl5005s_SetRfFreqHz( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - unsigned long RfFreqHz - ) +// funcs +u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value); +u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value); +u16 MXL_GetMasterControl(u8 *MasterReg, int state); +void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal); +u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count); +u32 MXL_Ceiling(u32 value, u32 resolution); +u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal); +u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal); +u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u16 controlGroup); +u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val); +u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count); +u32 MXL_GetXtalInt(u32 Xtal_Freq); +u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq); +void MXL_SynthIFLO_Calc(struct dvb_frontend *fe); +void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe); +u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count); +int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen); +u16 MXL_IFSynthInit(struct dvb_frontend *fe); + +int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) { - MXL5005S_EXTRA_MODULE *pExtra; - BASE_INTERFACE_MODULE *pBaseInterface; - - unsigned char AgcMasterByte; + struct mxl5005s_state *state = fe->tuner_priv; + u8 AgcMasterByte = state->config->AgcMasterByte; unsigned char AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; unsigned char ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; int TableLen; - unsigned long IfDivval; + u32 IfDivval; unsigned char MasterControlByte; - // Get tuner extra module and base interface module. - pExtra = (MXL5005S_EXTRA_MODULE *)pTuner->pExtra; - pBaseInterface = pTuner->pBaseInterface; - - - // Get AGC master byte - AgcMasterByte = pExtra->AgcMasterByte; - + dprintk(1, "%s() freq=%ld\n", __func__, RfFreqHz); // Set MxL5005S tuner RF frequency according to MxL5005S tuner example code. // Tuner RF frequency setting stage 0 MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET) ; AddrTable[0] = MASTER_CONTROL_ADDR; - ByteTable[0] |= AgcMasterByte; - - if(pExtra->SetRegsWithTable( dib,pTuner, AddrTable, ByteTable, LEN_1_BYTE) != FUNCTION_SUCCESS) - goto error_status_set_tuner_registers; + ByteTable[0] |= state->config->AgcMasterByte; + mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1); // Tuner RF frequency setting stage 1 - MXL_TuneRF(&pExtra->MxlDefinedTunerStructure, RfFreqHz); - - MXL_ControlRead(&pExtra->MxlDefinedTunerStructure, IF_DIVVAL, &IfDivval); + MXL_TuneRF(fe, RfFreqHz); - MXL_ControlWrite(&pExtra->MxlDefinedTunerStructure, SEQ_FSM_PULSE, 0); - MXL_ControlWrite(&pExtra->MxlDefinedTunerStructure, SEQ_EXTPOWERUP, 1); - MXL_ControlWrite(&pExtra->MxlDefinedTunerStructure, IF_DIVVAL, 8); + MXL_ControlRead(fe, IF_DIVVAL, &IfDivval); - MXL_GetCHRegister(&pExtra->MxlDefinedTunerStructure, AddrTable, ByteTable, &TableLen) ; + MXL_ControlWrite(fe, SEQ_FSM_PULSE, 0); + MXL_ControlWrite(fe, SEQ_EXTPOWERUP, 1); + MXL_ControlWrite(fe, IF_DIVVAL, 8); + MXL_GetCHRegister(fe, AddrTable, ByteTable, &TableLen) ; MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ; AddrTable[TableLen] = MASTER_CONTROL_ADDR ; ByteTable[TableLen] = MasterControlByte | AgcMasterByte; TableLen += 1; - if(pExtra->SetRegsWithTable( dib,pTuner, AddrTable, ByteTable, TableLen) != FUNCTION_SUCCESS) - goto error_status_set_tuner_registers; - + mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); // Wait 30 ms. - pBaseInterface->WaitMs(pBaseInterface, 30); - + msleep(30); // Tuner RF frequency setting stage 2 - MXL_ControlWrite(&pExtra->MxlDefinedTunerStructure, SEQ_FSM_PULSE, 1) ; - MXL_ControlWrite(&pExtra->MxlDefinedTunerStructure, IF_DIVVAL, IfDivval) ; - MXL_GetCHRegister_ZeroIF(&pExtra->MxlDefinedTunerStructure, AddrTable, ByteTable, &TableLen) ; + MXL_ControlWrite(fe, SEQ_FSM_PULSE, 1) ; + MXL_ControlWrite(fe, IF_DIVVAL, IfDivval) ; + MXL_GetCHRegister_ZeroIF(fe, AddrTable, ByteTable, &TableLen) ; MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ; AddrTable[TableLen] = MASTER_CONTROL_ADDR ; ByteTable[TableLen] = MasterControlByte | AgcMasterByte ; TableLen += 1; - if(pExtra->SetRegsWithTable( dib,pTuner, AddrTable, ByteTable, TableLen) != FUNCTION_SUCCESS) - goto error_status_set_tuner_registers; - - - // Set tuner RF frequency parameter. - pTuner->RfFreqHz = RfFreqHz; - pTuner->IsRfFreqHzSet = YES; - - - return FUNCTION_SUCCESS; - + mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); -error_status_set_tuner_registers: - return FUNCTION_ERROR; + return 0; } -// DONE -int mxl5005s_GetRfFreqHz(struct dvb_frontend *fe, unsigned long *pRfFreqHz) +/* Write a single byte to a single reg */ +static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val) { - struct mxl5005s_state *state = fe->demodulator_priv; - int ret = -1; - - /* Get tuner RF frequency in Hz from tuner module. */ - if(state->IsRfFreqHzSet == YES) { - *pRfFreqHz = state->RfFreqHz; - ret = 0; + struct mxl5005s_state *state = fe->tuner_priv; + u8 buf[2] = { reg, val }; + struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, + .buf = buf, .len = 2 }; + + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + printk(KERN_WARNING "mxl5005s I2C write failed\n"); + return -EREMOTEIO; } - - return -1; + return 0; } -int mxl5005s_SetRegsWithTable( - struct dvb_usb_device* dib, - TUNER_MODULE *pTuner, - unsigned char *pAddrTable, - unsigned char *pByteTable, - int TableLen - ) +/* Write a word to a single reg */ +static int mxl5005s_writereg16(struct dvb_frontend *fe, u8 reg, u16 val) { - BASE_INTERFACE_MODULE *pBaseInterface; - I2C_BRIDGE_MODULE *pI2cBridge; - unsigned char WritingByteNumMax; - - int i; - unsigned char WritingBuffer[I2C_BUFFER_LEN]; - unsigned char WritingIndex; - - - - // Get base interface, I2C bridge, and maximum writing byte number. - pBaseInterface = pTuner->pBaseInterface; - pI2cBridge = pTuner->pI2cBridge; - WritingByteNumMax = pBaseInterface->I2cWritingByteNumMax; - - - // Set registers with table. - // Note: 1. The I2C format of MxL5005S is described as follows: - // start_bit + (device_addr | writing_bit) + (register_addr + writing_byte) * n + stop_bit - // ... - // start_bit + (device_addr | writing_bit) + (register_addr + writing_byte) * m + latch_byte + stop_bit - // 2. The latch_byte is 0xfe. - // 3. The following writing byte separating scheme takes latch_byte as two byte data. - for(i = 0, WritingIndex = 0; i < TableLen; i++) - { - // Put register address and register byte value into writing buffer. - WritingBuffer[WritingIndex] = pAddrTable[i]; - WritingBuffer[WritingIndex + 1] = pByteTable[i]; - WritingIndex += 2; - - // If writing buffer is full, send the I2C writing command with writing buffer. - if(WritingIndex > (WritingByteNumMax - 2)) - { - if(pI2cBridge->ForwardI2cWritingCmd(pI2cBridge, WritingBuffer, WritingIndex) != FUNCTION_SUCCESS) - goto error_status_set_tuner_registers; - - WritingIndex = 0; - } + struct mxl5005s_state *state = fe->tuner_priv; + u8 buf[3] = { reg, val >> 8 , val & 0xff }; + struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, + .buf = buf, .len = 3 }; + + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + printk(KERN_WARNING "mxl5005s I2C write16 failed\n"); + return -EREMOTEIO; } - - - // Send the last I2C writing command with writing buffer and latch byte. - WritingBuffer[WritingIndex] = MXL5005S_LATCH_BYTE; - WritingIndex += 1; - - if(pI2cBridge->ForwardI2cWritingCmd(pI2cBridge, WritingBuffer, WritingIndex) != FUNCTION_SUCCESS) - goto error_status_set_tuner_registers; - - - return FUNCTION_SUCCESS; - - -error_status_set_tuner_registers: - return FUNCTION_ERROR; + return 0; } -int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, - unsigned char *pAddrTable, - unsigned char *pByteTable, - int TableLen - ) +int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen) { - struct mxl5005s_state *state = fe->demodulator_priv; - int i; + int i, ret; u8 end_two_bytes_buf[]={ 0 , 0 }; - u8 tuner_addr=0x00; - - pTuner->GetDeviceAddr(pTuner , &tuner_addr); for( i = 0 ; i < TableLen - 1 ; i++) { - if ( TUNER_WI2C(dib , tuner_addr , pAddrTable[i] , &pByteTable[i] , 1 ) ) - return FUNCTION_ERROR; + ret = mxl5005s_writereg(fe, pAddrTable[i], pByteTable[i]); + if (!ret) + return ret; } end_two_bytes_buf[0] = pByteTable[i]; end_two_bytes_buf[1] = MXL5005S_LATCH_BYTE; - if ( TUNER_WI2C(dib , tuner_addr , pAddrTable[i] , end_two_bytes_buf , 2 ) ) - return FUNCTION_ERROR; + ret = mxl5005s_writereg16(fe, pAddrTable[i], (end_two_bytes_buf[0] << 8) | end_two_bytes_buf[1]); - return FUNCTION_SUCCESS; + return ret; } int mxl5005s_SetRegMaskBits(struct dvb_frontend *fe, @@ -321,7 +482,6 @@ int mxl5005s_SetRegMaskBits(struct dvb_frontend *fe, const unsigned char WritingValue ) { - struct mxl5005s_state *state = fe->demodulator_priv; int i; unsigned char Mask; @@ -335,82 +495,18 @@ int mxl5005s_SetRegMaskBits(struct dvb_frontend *fe, Shift = Lsb; - /* Get tuner register byte according to register adddress. */ - MXL_RegRead(&pExtra->MxlDefinedTunerStructure, RegAddr, &RegByte); + MXL_RegRead(fe, RegAddr, &RegByte); /* Reserve register byte unmask bit with mask and inlay writing value into it. */ RegByte &= ~Mask; RegByte |= (WritingValue << Shift) & Mask; /* Update tuner register byte table. */ - MXL_RegWrite(&pExtra->MxlDefinedTunerStructure, RegAddr, RegByte); + MXL_RegWrite(fe, RegAddr, RegByte); /* Write tuner register byte with writing byte. */ - if(pExtra->SetRegsWithTable( dib, pTuner, &RegAddr, &RegByte, LEN_1_BYTE) != FUNCTION_SUCCESS) - goto error_status_set_tuner_registers; - - - return FUNCTION_SUCCESS; - - -error_status_set_tuner_registers: - return FUNCTION_ERROR; -} - -// DONE -int mxl5005s_SetSpectrumMode(struct dvb_frontend *fe, int SpectrumMode) -{ - struct mxl5005s_state *state = fe->demodulator_priv; - static const unsigned char BbIqswapTable[SPECTRUM_MODE_NUM] = - { - /* BB_IQSWAP */ - 0, /* Normal spectrum */ - 1, /* Inverse spectrum */ - }; - - /* Set BB_IQSWAP according to BB_IQSWAP table and spectrum mode. */ - mxl5005s_SetRegMaskBits(fe, - MXL5005S_BB_IQSWAP_ADDR, - MXL5005S_BB_IQSWAP_MSB, - MXL5005S_BB_IQSWAP_LSB, - BbIqswapTable[SpectrumMode]); - - return FUNCTION_SUCCESS; -} - -// DONE -int mxl5005s_SetBandwidthHz(struct dvb_frontend *fe, unsigned long BandwidthHz) -{ - struct mxl5005s_state *state = fe->demodulator_priv; - - unsigned char BbDlpfBandsel; - - /* Set BB_DLPF_BANDSEL according to bandwidth. */ - switch(BandwidthHz) - { - default: - case MXL5005S_BANDWIDTH_6MHZ: - BbDlpfBandsel = 3; - break; - case MXL5005S_BANDWIDTH_7MHZ: - BbDlpfBandsel = 2; - break; - case MXL5005S_BANDWIDTH_8MHZ: - BbDlpfBandsel = 0; - break; - } - - if(pExtra->SetRegMaskBits(dib,pTuner, MXL5005S_BB_DLPF_BANDSEL_ADDR, MXL5005S_BB_DLPF_BANDSEL_MSB, - MXL5005S_BB_DLPF_BANDSEL_LSB, BbDlpfBandsel) != 0) - goto error_status_set_tuner_registers; - - - return 0; - - -error_status_set_tuner_registers: - return -1; + return mxl5005s_SetRegsWithTable(fe, &RegAddr, &RegByte, 1); } // The following context is source code provided by MaxLinear. @@ -418,7 +514,7 @@ error_status_set_tuner_registers: // DONE u16 MXL5005_RegisterInit(struct dvb_frontend *fe) { - struct mxl5005s_state *state = fe->demodulator_priv; + struct mxl5005s_state *state = fe->tuner_priv; state->TunerRegs_Num = TUNER_REGS_NUM ; // state->TunerRegs = (TunerReg_struct *) calloc( TUNER_REGS_NUM, sizeof(TunerReg_struct) ) ; @@ -740,7 +836,7 @@ u16 MXL5005_RegisterInit(struct dvb_frontend *fe) // DONE u16 MXL5005_ControlInit(struct dvb_frontend *fe) { - struct mxl5005s_state *state = fe->demodulator_priv; + struct mxl5005s_state *state = fe->tuner_priv; state->Init_Ctrl_Num = INITCTRL_NUM; state->Init_Ctrl[0].Ctrl_Num = DN_IQTN_AMP_CUT ; @@ -1684,7 +1780,6 @@ u16 MXL5005_ControlInit(struct dvb_frontend *fe) // DONE void InitTunerControls(struct dvb_frontend *fe) { - struct mxl5005s_state *state = fe->demodulator_priv; MXL5005_RegisterInit(fe); MXL5005_ControlInit(fe); #ifdef _MXL_INTERNAL @@ -1745,7 +1840,7 @@ u16 MXL5005_TunerConfig(struct dvb_frontend *fe, /* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */ ) { - struct mxl5005s_state *state = fe->demodulator_priv; + struct mxl5005s_state *state = fe->tuner_priv; u16 status = 0; state->Mode = Mode; @@ -1798,8 +1893,8 @@ u16 MXL5005_TunerConfig(struct dvb_frontend *fe, // DONE void MXL_SynthIFLO_Calc(struct dvb_frontend *fe) { - struct mxl5005s_state *state = fe->demodulator_priv; - if (Tuner->Mode == 1) /* Digital Mode */ + struct mxl5005s_state *state = fe->tuner_priv; + if (state->Mode == 1) /* Digital Mode */ state->IF_LO = state->IF_OUT; else /* Analog Mode */ { @@ -1837,7 +1932,7 @@ void MXL_SynthIFLO_Calc(struct dvb_frontend *fe) // DONE void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe) { - struct mxl5005s_state *state = fe->demodulator_priv; + struct mxl5005s_state *state = fe->tuner_priv; if (state->Mode == 1) /* Digital Mode */ { //remove 20.48MHz setting for 2.6.10 @@ -1876,7 +1971,6 @@ void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe) // DONE u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) { - struct mxl5005s_state *state = fe->demodulator_priv; u16 status = 0; status += MXL_ControlWrite(fe, OVERRIDE_1, 1); @@ -1915,7 +2009,7 @@ u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) // DONE u16 MXL_BlockInit(struct dvb_frontend *fe) { - struct mxl5005s_state *state = fe->demodulator_priv; + struct mxl5005s_state *state = fe->tuner_priv; u16 status = 0; status += MXL_OverwriteICDefault(fe); @@ -2096,7 +2190,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) status += MXL_ControlWrite(fe, RFSYN_R_DIV, 0); /* Misc Controls */ - if (state->Mode == 0 && Tuner->IF_Mode == 1) /* Analog LowIF mode */ + if (state->Mode == 0 && state->IF_Mode == 1) /* Analog LowIF mode */ status += MXL_ControlWrite(fe, SEQ_EXTIQFSMPULSE, 0); else status += MXL_ControlWrite(fe, SEQ_EXTIQFSMPULSE, 1); @@ -2155,7 +2249,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) } if (state->Mod_Type == MXL_ATSC) /* ATSC Mode */ { - Tuner->AGC_Mode = 1; /* Single AGC Mode */ + state->AGC_Mode = 1; /* Single AGC Mode */ /* Enable RSSI */ status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1); @@ -2203,7 +2297,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) } if (state->Mod_Type == MXL_ANALOG_CABLE) { /* Analog Cable Mode */ - /* Tuner->Mode = MXL_DIGITAL_MODE; */ + /* state->Mode = MXL_DIGITAL_MODE; */ state->AGC_Mode = 1; /* Single AGC Mode */ @@ -2269,8 +2363,9 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -u16 MXL_IFSynthInit(Tuner_struct * Tuner) +u16 MXL_IFSynthInit(struct dvb_frontend *fe) { + struct mxl5005s_state *state = fe->tuner_priv; u16 status = 0 ; // Declare Local Variables u32 Fref = 0 ; @@ -2286,186 +2381,186 @@ u16 MXL_IFSynthInit(Tuner_struct * Tuner) // // IF Synthesizer Control // - if (Tuner->Mode == 0 && Tuner->IF_Mode == 1) // Analog Low IF mode + if (state->Mode == 0 && state->IF_Mode == 1) // Analog Low IF mode { - if (Tuner->IF_LO == 41000000UL) { + if (state->IF_LO == 41000000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 328000000UL ; } - if (Tuner->IF_LO == 47000000UL) { + if (state->IF_LO == 47000000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 376000000UL ; } - if (Tuner->IF_LO == 54000000UL) { + if (state->IF_LO == 54000000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 324000000UL ; } - if (Tuner->IF_LO == 60000000UL) { + if (state->IF_LO == 60000000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 360000000UL ; } - if (Tuner->IF_LO == 39250000UL) { + if (state->IF_LO == 39250000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 314000000UL ; } - if (Tuner->IF_LO == 39650000UL) { + if (state->IF_LO == 39650000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 317200000UL ; } - if (Tuner->IF_LO == 40150000UL) { + if (state->IF_LO == 40150000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 321200000UL ; } - if (Tuner->IF_LO == 40650000UL) { + if (state->IF_LO == 40650000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 325200000UL ; } } - if (Tuner->Mode || (Tuner->Mode == 0 && Tuner->IF_Mode == 0)) + if (state->Mode || (state->Mode == 0 && state->IF_Mode == 0)) { - if (Tuner->IF_LO == 57000000UL) { + if (state->IF_LO == 57000000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 342000000UL ; } - if (Tuner->IF_LO == 44000000UL) { + if (state->IF_LO == 44000000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 352000000UL ; } - if (Tuner->IF_LO == 43750000UL) { + if (state->IF_LO == 43750000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 350000000UL ; } - if (Tuner->IF_LO == 36650000UL) { + if (state->IF_LO == 36650000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 366500000UL ; } - if (Tuner->IF_LO == 36150000UL) { + if (state->IF_LO == 36150000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 361500000UL ; } - if (Tuner->IF_LO == 36000000UL) { + if (state->IF_LO == 36000000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 360000000UL ; } - if (Tuner->IF_LO == 35250000UL) { + if (state->IF_LO == 35250000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 352500000UL ; } - if (Tuner->IF_LO == 34750000UL) { + if (state->IF_LO == 34750000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 347500000UL ; } - if (Tuner->IF_LO == 6280000UL) { + if (state->IF_LO == 6280000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 376800000UL ; } - if (Tuner->IF_LO == 5000000UL) { + if (state->IF_LO == 5000000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 360000000UL ; } - if (Tuner->IF_LO == 4500000UL) { + if (state->IF_LO == 4500000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 360000000UL ; } - if (Tuner->IF_LO == 4570000UL) { + if (state->IF_LO == 4570000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 365600000UL ; } - if (Tuner->IF_LO == 4000000UL) { + if (state->IF_LO == 4000000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x05) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 360000000UL ; } - if (Tuner->IF_LO == 57400000UL) + if (state->IF_LO == 57400000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 344400000UL ; } - if (Tuner->IF_LO == 44400000UL) + if (state->IF_LO == 44400000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 355200000UL ; } - if (Tuner->IF_LO == 44150000UL) + if (state->IF_LO == 44150000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 353200000UL ; } - if (Tuner->IF_LO == 37050000UL) + if (state->IF_LO == 37050000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 370500000UL ; } - if (Tuner->IF_LO == 36550000UL) + if (state->IF_LO == 36550000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 365500000UL ; } - if (Tuner->IF_LO == 36125000UL) { + if (state->IF_LO == 36125000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 361250000UL ; } - if (Tuner->IF_LO == 6000000UL) { + if (state->IF_LO == 6000000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 360000000UL ; } - if (Tuner->IF_LO == 5400000UL) + if (state->IF_LO == 5400000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 324000000UL ; } - if (Tuner->IF_LO == 5380000UL) { + if (state->IF_LO == 5380000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 322800000UL ; } - if (Tuner->IF_LO == 5200000UL) { + if (state->IF_LO == 5200000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 374400000UL ; } - if (Tuner->IF_LO == 4900000UL) + if (state->IF_LO == 4900000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 352800000UL ; } - if (Tuner->IF_LO == 4400000UL) + if (state->IF_LO == 4400000UL) { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; Fref = 352000000UL ; } - if (Tuner->IF_LO == 4063000UL) //add for 2.6.8 + if (state->IF_LO == 4063000UL) //add for 2.6.8 { status += MXL_ControlWrite(fe, IF_DIVVAL, 0x05) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; @@ -2542,7 +2637,7 @@ u32 MXL_GetXtalInt(u32 Xtal_Freq) /////////////////////////////////////////////////////////////////////////////// u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) { - struct mxl5005s_state *state = fe->demodulator_priv; + struct mxl5005s_state *state = fe->tuner_priv; // Declare Local Variables u16 status = 0; u32 divider_val, E3, E4, E5, E5A; @@ -3034,7 +3129,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) // // Off Chip Tracking Filter Control // - if (Tuner->TF_Type == MXL_TF_OFF) // Tracking Filter Off State; turn off all the banks + if (state->TF_Type == MXL_TF_OFF) // Tracking Filter Off State; turn off all the banks { status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; @@ -3044,7 +3139,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) status += MXL_SetGPIO(fe, 4, 1) ; // turn off Bank 3 } - if (Tuner->TF_Type == MXL_TF_C) // Tracking Filter type C + if (state->TF_Type == MXL_TF_C) // Tracking Filter type C { status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; status += MXL_ControlWrite(fe, DAC_DIN_A, 0) ; @@ -3124,7 +3219,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) } } - if (Tuner->TF_Type == MXL_TF_C_H) // Tracking Filter type C-H for Hauppauge only + if (state->TF_Type == MXL_TF_C_H) // Tracking Filter type C-H for Hauppauge only { status += MXL_ControlWrite(fe, DAC_DIN_A, 0) ; @@ -3194,7 +3289,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) } } - if (Tuner->TF_Type == MXL_TF_D) // Tracking Filter type D + if (state->TF_Type == MXL_TF_D) // Tracking Filter type D { status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; @@ -3251,7 +3346,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) } - if (Tuner->TF_Type == MXL_TF_D_L) // Tracking Filter type D-L for Lumanate ONLY change for 2.6.3 + if (state->TF_Type == MXL_TF_D_L) // Tracking Filter type D-L for Lumanate ONLY change for 2.6.3 { status += MXL_ControlWrite(fe, DAC_DIN_A, 0) ; @@ -3336,7 +3431,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) } } - if (Tuner->TF_Type == MXL_TF_E) // Tracking Filter type E + if (state->TF_Type == MXL_TF_E) // Tracking Filter type E { status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; @@ -3392,7 +3487,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) } } - if (Tuner->TF_Type == MXL_TF_F) // Tracking Filter type F + if (state->TF_Type == MXL_TF_F) // Tracking Filter type F { status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; @@ -3448,7 +3543,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) } } - if (Tuner->TF_Type == MXL_TF_E_2) // Tracking Filter type E_2 + if (state->TF_Type == MXL_TF_E_2) // Tracking Filter type E_2 { status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; @@ -3504,7 +3599,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) } } - if (Tuner->TF_Type == MXL_TF_G) // Tracking Filter type G add for v2.6.8 + if (state->TF_Type == MXL_TF_G) // Tracking Filter type G add for v2.6.8 { status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; @@ -3567,7 +3662,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) } } - if (Tuner->TF_Type == MXL_TF_E_NA) // Tracking Filter type E-NA for Empia ONLY change for 2.6.8 + if (state->TF_Type == MXL_TF_E_NA) // Tracking Filter type E-NA for Empia ONLY change for 2.6.8 { status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; @@ -3667,7 +3762,6 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) // DONE u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val) { - struct mxl5005s_state *state = fe->demodulator_priv; u16 status = 0; if (GPIO_Num == 1) @@ -3735,14 +3829,13 @@ u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val) // DONE u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value) { - struct mxl5005s_state *state = fe->demodulator_priv; u16 status = 0; /* Will write ALL Matching Control Name */ - status += MXL_ControlWrite_Group(fe, ControlNum, value, 1); /* Write Matching INIT Control * - status += MXL_ControlWrite_Group(fe, ControlNum, value, 2); /* Write Matching CH Control * + status += MXL_ControlWrite_Group(fe, ControlNum, value, 1); /* Write Matching INIT Control */ + status += MXL_ControlWrite_Group(fe, ControlNum, value, 2); /* Write Matching CH Control */ #ifdef _MXL_INTERNAL - status += MXL_ControlWrite_Group(fe, ControlNum, value, 3); /* Write Matching MXL Control * + status += MXL_ControlWrite_Group(fe, ControlNum, value, 3); /* Write Matching MXL Control */ #endif return status; } @@ -3777,7 +3870,7 @@ u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value) // DONE u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u16 controlGroup) { - struct mxl5005s_state *state = fe->demodulator_priv; + struct mxl5005s_state *state = fe->tuner_priv; u16 i, j, k; u32 highLimit; u32 ctrlVal; @@ -3884,7 +3977,7 @@ u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u // DONE u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) { - struct mxl5005s_state *state = fe->demodulator_priv; + struct mxl5005s_state *state = fe->tuner_priv; int i ; for (i = 0; i < 104; i++) { @@ -3924,7 +4017,7 @@ u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) // DONE u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) { - struct mxl5005s_state *state = fe->demodulator_priv; + struct mxl5005s_state *state = fe->tuner_priv; int i ; for (i = 0; i < 104; i++) { @@ -3959,9 +4052,9 @@ u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) // // /////////////////////////////////////////////////////////////////////////////// // DONE -u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 * value) +u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value) { - struct mxl5005s_state *state = fe->demodulator_priv; + struct mxl5005s_state *state = fe->tuner_priv; u32 ctrlVal ; u16 i, k ; @@ -4033,7 +4126,7 @@ u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 * value) // DONE u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int * count) { - struct mxl5005s_state *state = fe->demodulator_priv; + struct mxl5005s_state *state = fe->tuner_priv; u16 i, j, k ; u16 Count ; @@ -4139,7 +4232,7 @@ u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int // DONE void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal) { - struct mxl5005s_state *state = fe->demodulator_priv; + struct mxl5005s_state *state = fe->tuner_priv; int i ; const u8 AND_MAP[8] = { @@ -4196,7 +4289,6 @@ u32 MXL_Ceiling(u32 value, u32 resolution) // DONE u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { - struct mxl5005s_state *state = fe->demodulator_priv; u16 status = 0; int i ; @@ -4220,7 +4312,6 @@ u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *c // DONE u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { - struct mxl5005s_state *state = fe->demodulator_priv; u16 status = 0; int i ; @@ -4249,7 +4340,6 @@ u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *cou // DONE u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { - struct mxl5005s_state *state = fe->demodulator_priv; u16 status = 0; int i; @@ -4268,7 +4358,6 @@ u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, i // DONE u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { - struct mxl5005s_state *state = fe->demodulator_priv; u16 status = 0; int i; @@ -4302,7 +4391,7 @@ u16 MXL_GetMasterControl(u8 *MasterReg, int state) #ifdef _MXL_PRODUCTION u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range) { - struct mxl5005s_state *state = fe->demodulator_priv; + struct mxl5005s_state *state = fe->tuner_priv; u16 status = 0 ; if (VCO_Range == 1) { @@ -4432,7 +4521,7 @@ u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range) // DONE u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis) { - struct mxl5005s_state *state = fe->demodulator_priv; + struct mxl5005s_state *state = fe->tuner_priv; u16 status = 0; if (Hystersis == 1) @@ -4443,3 +4532,194 @@ u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis) #endif +/* Linux driver related functions */ + + +int mxl5005s_init2(struct dvb_frontend *fe) +{ + int MxlModMode; + int MxlIfMode; + unsigned long MxlBandwitdh; + unsigned long MxlIfFreqHz; + unsigned long MxlCrystalFreqHz; + int MxlAgcMode; + unsigned short MxlTop; + unsigned short MxlIfOutputLoad; + int MxlClockOut; + int MxlDivOut; + int MxlCapSel; + int MxlRssiOnOff; + unsigned char MxlStandard; + unsigned char MxlTfType; + + /* Set MxL5005S parameters. */ + MxlModMode = MXL_DIGITAL_MODE; + MxlIfMode = MXL_ZERO_IF; +// steve + //MxlBandwitdh = MXL5005S_BANDWIDTH_8MHZ; + //MxlIfFreqHz = IF_FREQ_4570000HZ; + MxlBandwitdh = MXL5005S_BANDWIDTH_6MHZ; // config + MxlIfFreqHz = IF_FREQ_5380000HZ; // config + MxlCrystalFreqHz = CRYSTAL_FREQ_16000000HZ; // config + MxlAgcMode = MXL_SINGLE_AGC; + MxlTop = MXL5005S_TOP_25P2; + MxlIfOutputLoad = MXL5005S_IF_OUTPUT_LOAD_200_OHM; + MxlClockOut = MXL_CLOCK_OUT_DISABLE; + MxlDivOut = MXL_DIV_OUT_4; + MxlCapSel = MXL_CAP_SEL_ENABLE; + MxlRssiOnOff = MXL_RSSI_ENABLE; // config + MxlTfType = MXL_TF_C_H; // config + + MxlStandard = MXL_ATSC; // config + + // TODO: this is bad, it trashes other configs + // Set MxL5005S extra module. + //pExtra->AgcMasterByte = (MxlAgcMode == MXL_DUAL_AGC) ? 0x4 : 0x0; + + MXL5005_TunerConfig( + fe, + (unsigned char)MxlModMode, + (unsigned char)MxlIfMode, + MxlBandwitdh, + MxlIfFreqHz, + MxlCrystalFreqHz, + (unsigned char)MxlAgcMode, + MxlTop, + MxlIfOutputLoad, + (unsigned char)MxlClockOut, + (unsigned char)MxlDivOut, + (unsigned char)MxlCapSel, + (unsigned char)MxlRssiOnOff, + MxlStandard, MxlTfType); + + return 0; +} + +static int mxl5005s_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + u32 freq; + u32 bw; + + if (fe->ops.info.type == FE_OFDM) + bw = params->u.ofdm.bandwidth; + else + bw = MXL5005S_BANDWIDTH_6MHZ; + + freq = params->frequency; /* Hz */ + dprintk(1, "%s() freq=%d bw=%d\n", __func__, freq, bw); + + return mxl5005s_SetRfFreqHz(fe, freq); +} + +static int mxl5005s_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct mxl5005s_state *state = fe->tuner_priv; + dprintk(1, "%s()\n", __func__); + + *frequency = state->RF_IN; + + return 0; +} + +static int mxl5005s_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct mxl5005s_state *state = fe->tuner_priv; + dprintk(1, "%s()\n", __func__); + + *bandwidth = state->Chan_Bandwidth; + + return 0; +} + +static int mxl5005s_get_status(struct dvb_frontend *fe, u32 *status) +{ + dprintk(1, "%s()\n", __func__); + + *status = 0; + // *status = TUNER_STATUS_LOCKED; + + return 0; +} + +static int mxl5005s_init(struct dvb_frontend *fe) +{ + struct mxl5005s_state *state = fe->tuner_priv; + u8 AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; + u8 ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; + int TableLen; + + dprintk(1, "%s()\n", __func__); + + /* Initialize MxL5005S tuner according to MxL5005S tuner example code. */ + + /* Tuner initialization stage 0 */ + MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET); + AddrTable[0] = MASTER_CONTROL_ADDR; + ByteTable[0] |= state->config->AgcMasterByte; + + mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1); + + /* Tuner initialization stage 1 */ + MXL_GetInitRegister(fe, AddrTable, ByteTable, &TableLen); + + mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); + + return mxl5005s_init2(fe); +} + +static int mxl5005s_release(struct dvb_frontend *fe) +{ + dprintk(1, "%s()\n", __func__); + kfree(fe->tuner_priv); + fe->tuner_priv = NULL; + return 0; +} + +static const struct dvb_tuner_ops mxl5005s_tuner_ops = { + .info = { + .name = "MaxLinear MXL5005S", + .frequency_min = 48000000, + .frequency_max = 860000000, + .frequency_step = 50000, + }, + + .release = mxl5005s_release, + .init = mxl5005s_init, + + .set_params = mxl5005s_set_params, + .get_frequency = mxl5005s_get_frequency, + .get_bandwidth = mxl5005s_get_bandwidth, + .get_status = mxl5005s_get_status +}; + +struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + struct mxl5005s_config *config) +{ + struct mxl5005s_state *state = NULL; + dprintk(1, "%s()\n", __func__); + + state = kzalloc(sizeof(struct mxl5005s_state), GFP_KERNEL); + if (state == NULL) + return NULL; + + state->frontend = fe; + state->config = config; + state->i2c = i2c; + + printk(KERN_INFO "MXL5005S: Attached at address 0x%02x\n", config->i2c_address); + + memcpy(&fe->ops.tuner_ops, &mxl5005s_tuner_ops, sizeof(struct dvb_tuner_ops)); + + fe->tuner_priv = state; + return fe; +} +EXPORT_SYMBOL(mxl5005s_attach); + +MODULE_DESCRIPTION("MaxLinear MXL5005S silicon tuner driver"); +MODULE_AUTHOR("Jan Hoogenraad"); +MODULE_AUTHOR("Barnaby Shearer"); +MODULE_AUTHOR("Andy Hasper"); +MODULE_AUTHOR("Steven Toth"); +MODULE_LICENSE("GPL"); diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h index df49826..1c4d9da 100644 --- a/drivers/media/common/tuners/mxl5005s.h +++ b/drivers/media/common/tuners/mxl5005s.h @@ -26,273 +26,48 @@ #ifndef __MXL5005S_H #define __MXL5005S_H -/* - * The following context is source code provided by MaxLinear. - * MaxLinear source code - Common.h - */ - -typedef void *HANDLE; /* Pointer to memory location */ - -#define TUNER_REGS_NUM 104 -#define INITCTRL_NUM 40 - -#ifdef _MXL_PRODUCTION -#define CHCTRL_NUM 39 -#else -#define CHCTRL_NUM 36 -#endif - -#define MXLCTRL_NUM 189 -#define MASTER_CONTROL_ADDR 9 - -/* Enumeration of AGC Mode */ -typedef enum -{ - MXL_DUAL_AGC = 0, - MXL_SINGLE_AGC -} AGC_Mode; - -/* Enumeration of Master Control Register State */ -typedef enum -{ - MC_LOAD_START = 1, - MC_POWER_DOWN, - MC_SYNTH_RESET, - MC_SEQ_OFF -} Master_Control_State; - -/* Enumeration of MXL5005 Tuner Mode */ -typedef enum -{ - MXL_ANALOG_MODE = 0, - MXL_DIGITAL_MODE -} Tuner_Mode; - -/* Enumeration of MXL5005 Tuner IF Mode */ -typedef enum -{ - MXL_ZERO_IF = 0, - MXL_LOW_IF -} Tuner_IF_Mode; - -/* Enumeration of MXL5005 Tuner Clock Out Mode */ -typedef enum -{ - MXL_CLOCK_OUT_DISABLE = 0, - MXL_CLOCK_OUT_ENABLE -} Tuner_Clock_Out; - -/* Enumeration of MXL5005 Tuner Div Out Mode */ -typedef enum -{ - MXL_DIV_OUT_1 = 0, - MXL_DIV_OUT_4 - -} Tuner_Div_Out; - -/* Enumeration of MXL5005 Tuner Pull-up Cap Select Mode */ -typedef enum -{ - MXL_CAP_SEL_DISABLE = 0, - MXL_CAP_SEL_ENABLE - -} Tuner_Cap_Select; - -/* Enumeration of MXL5005 Tuner RSSI Mode */ -typedef enum -{ - MXL_RSSI_DISABLE = 0, - MXL_RSSI_ENABLE - -} Tuner_RSSI; - -/* Enumeration of MXL5005 Tuner Modulation Type */ -typedef enum -{ - MXL_DEFAULT_MODULATION = 0, - MXL_DVBT, - MXL_ATSC, - MXL_QAM, - MXL_ANALOG_CABLE, - MXL_ANALOG_OTA -} Tuner_Modu_Type; - -/* Enumeration of MXL5005 Tuner Tracking Filter Type */ -typedef enum -{ - MXL_TF_DEFAULT = 0, - MXL_TF_OFF, - MXL_TF_C, - MXL_TF_C_H, - MXL_TF_D, - MXL_TF_D_L, - MXL_TF_E, - MXL_TF_F, - MXL_TF_E_2, - MXL_TF_E_NA, - MXL_TF_G -} Tuner_TF_Type; - -/* MXL5005 Tuner Register Struct */ -typedef struct _TunerReg_struct -{ - u16 Reg_Num; /* Tuner Register Address */ - u16 Reg_Val; /* Current sofware programmed value waiting to be writen */ -} TunerReg_struct; - -typedef enum -{ - /* Initialization Control Names */ - DN_IQTN_AMP_CUT = 1, /* 1 */ - BB_MODE, /* 2 */ - BB_BUF, /* 3 */ - BB_BUF_OA, /* 4 */ - BB_ALPF_BANDSELECT, /* 5 */ - BB_IQSWAP, /* 6 */ - BB_DLPF_BANDSEL, /* 7 */ - RFSYN_CHP_GAIN, /* 8 */ - RFSYN_EN_CHP_HIGAIN, /* 9 */ - AGC_IF, /* 10 */ - AGC_RF, /* 11 */ - IF_DIVVAL, /* 12 */ - IF_VCO_BIAS, /* 13 */ - CHCAL_INT_MOD_IF, /* 14 */ - CHCAL_FRAC_MOD_IF, /* 15 */ - DRV_RES_SEL, /* 16 */ - I_DRIVER, /* 17 */ - EN_AAF, /* 18 */ - EN_3P, /* 19 */ - EN_AUX_3P, /* 20 */ - SEL_AAF_BAND, /* 21 */ - SEQ_ENCLK16_CLK_OUT, /* 22 */ - SEQ_SEL4_16B, /* 23 */ - XTAL_CAPSELECT, /* 24 */ - IF_SEL_DBL, /* 25 */ - RFSYN_R_DIV, /* 26 */ - SEQ_EXTSYNTHCALIF, /* 27 */ - SEQ_EXTDCCAL, /* 28 */ - AGC_EN_RSSI, /* 29 */ - RFA_ENCLKRFAGC, /* 30 */ - RFA_RSSI_REFH, /* 31 */ - RFA_RSSI_REF, /* 32 */ - RFA_RSSI_REFL, /* 33 */ - RFA_FLR, /* 34 */ - RFA_CEIL, /* 35 */ - SEQ_EXTIQFSMPULSE, /* 36 */ - OVERRIDE_1, /* 37 */ - BB_INITSTATE_DLPF_TUNE, /* 38 */ - TG_R_DIV, /* 39 */ - EN_CHP_LIN_B, /* 40 */ - - /* Channel Change Control Names */ - DN_POLY = 51, /* 51 */ - DN_RFGAIN, /* 52 */ - DN_CAP_RFLPF, /* 53 */ - DN_EN_VHFUHFBAR, /* 54 */ - DN_GAIN_ADJUST, /* 55 */ - DN_IQTNBUF_AMP, /* 56 */ - DN_IQTNGNBFBIAS_BST, /* 57 */ - RFSYN_EN_OUTMUX, /* 58 */ - RFSYN_SEL_VCO_OUT, /* 59 */ - RFSYN_SEL_VCO_HI, /* 60 */ - RFSYN_SEL_DIVM, /* 61 */ - RFSYN_RF_DIV_BIAS, /* 62 */ - DN_SEL_FREQ, /* 63 */ - RFSYN_VCO_BIAS, /* 64 */ - CHCAL_INT_MOD_RF, /* 65 */ - CHCAL_FRAC_MOD_RF, /* 66 */ - RFSYN_LPF_R, /* 67 */ - CHCAL_EN_INT_RF, /* 68 */ - TG_LO_DIVVAL, /* 69 */ - TG_LO_SELVAL, /* 70 */ - TG_DIV_VAL, /* 71 */ - TG_VCO_BIAS, /* 72 */ - SEQ_EXTPOWERUP, /* 73 */ - OVERRIDE_2, /* 74 */ - OVERRIDE_3, /* 75 */ - OVERRIDE_4, /* 76 */ - SEQ_FSM_PULSE, /* 77 */ - GPIO_4B, /* 78 */ - GPIO_3B, /* 79 */ - GPIO_4, /* 80 */ - GPIO_3, /* 81 */ - GPIO_1B, /* 82 */ - DAC_A_ENABLE, /* 83 */ - DAC_B_ENABLE, /* 84 */ - DAC_DIN_A, /* 85 */ - DAC_DIN_B, /* 86 */ -#ifdef _MXL_PRODUCTION - RFSYN_EN_DIV, /* 87 */ - RFSYN_DIVM, /* 88 */ - DN_BYPASS_AGC_I2C /* 89 */ -#endif -} MXL5005_ControlName; - -/* End of common.h */ - -/* - * The following context is source code provided by MaxLinear. - * MaxLinear source code - Common_MXL.h (?) - */ - -/* Constants */ -#define MXL5005S_REG_WRITING_TABLE_LEN_MAX 104 -#define MXL5005S_LATCH_BYTE 0xfe - -/* Register address, MSB, and LSB */ -#define MXL5005S_BB_IQSWAP_ADDR 59 -#define MXL5005S_BB_IQSWAP_MSB 0 -#define MXL5005S_BB_IQSWAP_LSB 0 - -#define MXL5005S_BB_DLPF_BANDSEL_ADDR 53 -#define MXL5005S_BB_DLPF_BANDSEL_MSB 4 -#define MXL5005S_BB_DLPF_BANDSEL_LSB 3 - -/* Standard modes */ -enum -{ - MXL5005S_STANDARD_DVBT, - MXL5005S_STANDARD_ATSC, +/* IF frequency */ +enum IF_FREQ_HZ +{ + IF_FREQ_4570000HZ = 4570000, ///< IF frequency = 4.57 MHz + IF_FREQ_4571429HZ = 4571429, ///< IF frequency = 4.571 MHz + IF_FREQ_5380000HZ = 5380000, ///< IF frequency = 5.38 MHz + IF_FREQ_36000000HZ = 36000000, ///< IF frequency = 36.000 MHz + IF_FREQ_36125000HZ = 36125000, ///< IF frequency = 36.125 MHz + IF_FREQ_36166667HZ = 36166667, ///< IF frequency = 36.167 MHz + IF_FREQ_44000000HZ = 44000000, ///< IF frequency = 44.000 MHz }; -#define MXL5005S_STANDARD_MODE_NUM 2 -/* Bandwidth modes */ -enum +/* Crystal frequency */ +enum CRYSTAL_FREQ_HZ { - MXL5005S_BANDWIDTH_6MHZ = 6000000, - MXL5005S_BANDWIDTH_7MHZ = 7000000, - MXL5005S_BANDWIDTH_8MHZ = 8000000, + CRYSTAL_FREQ_4000000HZ = 4000000, ///< Crystal frequency = 4.0 MHz + CRYSTAL_FREQ_16000000HZ = 16000000, ///< Crystal frequency = 16.0 MHz + CRYSTAL_FREQ_25000000HZ = 25000000, ///< Crystal frequency = 25.0 MHz + CRYSTAL_FREQ_28800000HZ = 28800000, ///< Crystal frequency = 28.8 MHz }; -#define MXL5005S_BANDWIDTH_MODE_NUM 3 -/* Top modes */ -enum +struct mxl5005s_config { - MXL5005S_TOP_5P5 = 55, - MXL5005S_TOP_7P2 = 72, - MXL5005S_TOP_9P2 = 92, - MXL5005S_TOP_11P0 = 110, - MXL5005S_TOP_12P9 = 129, - MXL5005S_TOP_14P7 = 147, - MXL5005S_TOP_16P8 = 168, - MXL5005S_TOP_19P4 = 194, - MXL5005S_TOP_21P2 = 212, - MXL5005S_TOP_23P2 = 232, - MXL5005S_TOP_25P2 = 252, - MXL5005S_TOP_27P1 = 271, - MXL5005S_TOP_29P2 = 292, - MXL5005S_TOP_31P7 = 317, - MXL5005S_TOP_34P9 = 349, -}; + u8 i2c_address; -/* IF output load */ -enum -{ - MXL5005S_IF_OUTPUT_LOAD_200_OHM = 200, - MXL5005S_IF_OUTPUT_LOAD_300_OHM = 300, + /* Stuff I don't know what to do with */ + u8 AgcMasterByte; }; -/* End of common_mxl.h (?) */ +#if defined(CONFIG_DVB_TUNER_MXL5005S) || (defined(CONFIG_DVB_TUNER_MXL5005S_MODULE) && defined(MODULE)) +extern struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + struct mxl5005s_config *config); +#else +static inline struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + struct mxl5005s_config *config); +{ + printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); + return NULL; +} +#endif /* CONFIG_DVB_TUNER_MXL5005S */ #endif /* __MXL5005S_H */ -- cgit v1.1 From 8c66a19d45fb5b88abf10678db353f35179a2cde Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 1 May 2008 06:35:48 -0300 Subject: V4L/DVB (7868): mxl5005s: Cleanup #5 Cleanup #5 Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 304 +++++++++++---------------------- drivers/media/common/tuners/mxl5005s.h | 99 ++++++++--- 2 files changed, 181 insertions(+), 222 deletions(-) diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index 7e68717..aad88d5 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -24,10 +24,10 @@ #include "mxl5005s.h" -static int debug; +static int debug = 2; #define dprintk(level, arg...) do { \ - if (debug >= level) \ + if (level <= debug) \ printk(arg); \ } while (0) @@ -43,13 +43,6 @@ static int debug; #define MXLCTRL_NUM 189 #define MASTER_CONTROL_ADDR 9 -/* Enumeration of AGC Mode */ -typedef enum -{ - MXL_DUAL_AGC = 0, - MXL_SINGLE_AGC -} AGC_Mode; - /* Enumeration of Master Control Register State */ typedef enum { @@ -59,51 +52,6 @@ typedef enum MC_SEQ_OFF } Master_Control_State; -/* Enumeration of MXL5005 Tuner Mode */ -typedef enum -{ - MXL_ANALOG_MODE = 0, - MXL_DIGITAL_MODE -} Tuner_Mode; - -/* Enumeration of MXL5005 Tuner IF Mode */ -typedef enum -{ - MXL_ZERO_IF = 0, - MXL_LOW_IF -} Tuner_IF_Mode; - -/* Enumeration of MXL5005 Tuner Clock Out Mode */ -typedef enum -{ - MXL_CLOCK_OUT_DISABLE = 0, - MXL_CLOCK_OUT_ENABLE -} Tuner_Clock_Out; - -/* Enumeration of MXL5005 Tuner Div Out Mode */ -typedef enum -{ - MXL_DIV_OUT_1 = 0, - MXL_DIV_OUT_4 - -} Tuner_Div_Out; - -/* Enumeration of MXL5005 Tuner Pull-up Cap Select Mode */ -typedef enum -{ - MXL_CAP_SEL_DISABLE = 0, - MXL_CAP_SEL_ENABLE - -} Tuner_Cap_Select; - -/* Enumeration of MXL5005 Tuner RSSI Mode */ -typedef enum -{ - MXL_RSSI_DISABLE = 0, - MXL_RSSI_ENABLE - -} Tuner_RSSI; - /* Enumeration of MXL5005 Tuner Modulation Type */ typedef enum { @@ -115,22 +63,6 @@ typedef enum MXL_ANALOG_OTA } Tuner_Modu_Type; -/* Enumeration of MXL5005 Tuner Tracking Filter Type */ -typedef enum -{ - MXL_TF_DEFAULT = 0, - MXL_TF_OFF, - MXL_TF_C, - MXL_TF_C_H, - MXL_TF_D, - MXL_TF_D_L, - MXL_TF_E, - MXL_TF_F, - MXL_TF_E_2, - MXL_TF_E_NA, - MXL_TF_G -} Tuner_TF_Type; - /* MXL5005 Tuner Register Struct */ typedef struct _TunerReg_struct { @@ -261,33 +193,6 @@ enum }; #define MXL5005S_BANDWIDTH_MODE_NUM 3 -/* Top modes */ -enum -{ - MXL5005S_TOP_5P5 = 55, - MXL5005S_TOP_7P2 = 72, - MXL5005S_TOP_9P2 = 92, - MXL5005S_TOP_11P0 = 110, - MXL5005S_TOP_12P9 = 129, - MXL5005S_TOP_14P7 = 147, - MXL5005S_TOP_16P8 = 168, - MXL5005S_TOP_19P4 = 194, - MXL5005S_TOP_21P2 = 212, - MXL5005S_TOP_23P2 = 232, - MXL5005S_TOP_25P2 = 252, - MXL5005S_TOP_27P1 = 271, - MXL5005S_TOP_29P2 = 292, - MXL5005S_TOP_31P7 = 317, - MXL5005S_TOP_34P9 = 349, -}; - -/* IF output load */ -enum -{ - MXL5005S_IF_OUTPUT_LOAD_200_OHM = 200, - MXL5005S_IF_OUTPUT_LOAD_300_OHM = 300, -}; - /* MXL5005 Tuner Control Struct */ typedef struct _TunerControl_struct { u16 Ctrl_Num; /* Control Number */ @@ -342,8 +247,7 @@ struct mxl5005s_state TunerRegs[TUNER_REGS_NUM]; /* Tuner Register Array Pointer */ /* Linux driver framework specific */ - const struct mxl5005s_config *config; - + struct mxl5005s_config *config; struct dvb_frontend *frontend; struct i2c_adapter *i2c; }; @@ -367,11 +271,11 @@ void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe); u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count); int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen); u16 MXL_IFSynthInit(struct dvb_frontend *fe); +int mxl5005s_AssignTunerMode(struct dvb_frontend *fe); int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) { struct mxl5005s_state *state = fe->tuner_priv; - u8 AgcMasterByte = state->config->AgcMasterByte; unsigned char AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; unsigned char ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; int TableLen; @@ -402,13 +306,13 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ; AddrTable[TableLen] = MASTER_CONTROL_ADDR ; - ByteTable[TableLen] = MasterControlByte | AgcMasterByte; + ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte; TableLen += 1; mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); // Wait 30 ms. - msleep(30); + msleep(150); // Tuner RF frequency setting stage 2 MXL_ControlWrite(fe, SEQ_FSM_PULSE, 1) ; @@ -417,39 +321,56 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ; AddrTable[TableLen] = MASTER_CONTROL_ADDR ; - ByteTable[TableLen] = MasterControlByte | AgcMasterByte ; + ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte ; TableLen += 1; mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); + msleep(100); + return 0; } -/* Write a single byte to a single reg */ -static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val) +static int mxl5005s_reset(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; - u8 buf[2] = { reg, val }; + int ret = 0; + + u8 buf[2] = { 0xff, 0x00 }; struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, .buf = buf, .len = 2 }; + dprintk(2, "%s()\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + if (i2c_transfer(state->i2c, &msg, 1) != 1) { - printk(KERN_WARNING "mxl5005s I2C write failed\n"); - return -EREMOTEIO; + printk(KERN_WARNING "mxl5005s I2C reset failed\n"); + ret = -EREMOTEIO; } - return 0; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return ret; } -/* Write a word to a single reg */ -static int mxl5005s_writereg16(struct dvb_frontend *fe, u8 reg, u16 val) +/* Write a single byte to a single reg */ +static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val, int latch) { struct mxl5005s_state *state = fe->tuner_priv; - u8 buf[3] = { reg, val >> 8 , val & 0xff }; + u8 buf[3] = { reg, val, MXL5005S_LATCH_BYTE }; struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, .buf = buf, .len = 3 }; + if(latch == 0) + msg.len = 2; + + dprintk(2, "%s(reg = 0x%x val = 0x%x addr = 0x%x)\n", __func__, reg, val, msg.addr); + if (i2c_transfer(state->i2c, &msg, 1) != 1) { - printk(KERN_WARNING "mxl5005s I2C write16 failed\n"); + printk(KERN_WARNING "mxl5005s I2C write failed\n"); return -EREMOTEIO; } return 0; @@ -457,20 +378,22 @@ static int mxl5005s_writereg16(struct dvb_frontend *fe, u8 reg, u16 val) int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen) { - int i, ret; - u8 end_two_bytes_buf[]={ 0 , 0 }; + int i, ret = 0; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); for( i = 0 ; i < TableLen - 1 ; i++) { - ret = mxl5005s_writereg(fe, pAddrTable[i], pByteTable[i]); - if (!ret) - return ret; + ret = mxl5005s_writereg(fe, pAddrTable[i], pByteTable[i], 0); + if (ret < 0) + break; } - end_two_bytes_buf[0] = pByteTable[i]; - end_two_bytes_buf[1] = MXL5005S_LATCH_BYTE; + ret = mxl5005s_writereg(fe, pAddrTable[i], pByteTable[i], 1); - ret = mxl5005s_writereg16(fe, pAddrTable[i], (end_two_bytes_buf[0] << 8) | end_two_bytes_buf[1]); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); return ret; } @@ -509,6 +432,7 @@ int mxl5005s_SetRegMaskBits(struct dvb_frontend *fe, return mxl5005s_SetRegsWithTable(fe, &RegAddr, &RegByte, 1); } + // The following context is source code provided by MaxLinear. // MaxLinear source code - MXL5005_Initialize.cpp // DONE @@ -2034,6 +1958,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 2); break; case 6000000: + printk("%s() doing 6MHz digital\n", __func__); status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 3); break; } @@ -2064,7 +1989,6 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) else /* Single AGC Mode Dig Ana */ status += MXL_ControlWrite(fe, AGC_RF, state->Mode ? 15 : 12); - if (state->TOP == 55) /* TOP == 5.5 */ status += MXL_ControlWrite(fe, AGC_IF, 0x0); @@ -2294,6 +2218,8 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) status += MXL_ControlWrite(fe, BB_IQSWAP, 0); else /* High IF */ status += MXL_ControlWrite(fe, BB_IQSWAP, 1); + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 2); + } if (state->Mod_Type == MXL_ANALOG_CABLE) { /* Analog Cable Mode */ @@ -2330,7 +2256,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) } /* RSSI disable */ - if(state->EN_RSSI==0) { + if(state->EN_RSSI == 0) { status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1); status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1); status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0); @@ -2539,6 +2465,7 @@ u16 MXL_IFSynthInit(struct dvb_frontend *fe) Fref = 324000000UL ; } if (state->IF_LO == 5380000UL) { + printk("%s() doing 5.38\n", __func__); status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 322800000UL ; @@ -3221,6 +3148,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) if (state->TF_Type == MXL_TF_C_H) // Tracking Filter type C-H for Hauppauge only { + printk("%s() CH filter\n", __func__); status += MXL_ControlWrite(fe, DAC_DIN_A, 0) ; if (state->RF_IN >= 43000000 && state->RF_IN < 150000000) @@ -4534,63 +4462,59 @@ u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis) /* Linux driver related functions */ +int mxl5005s_init(struct dvb_frontend *fe) +{ + struct mxl5005s_state *state = fe->tuner_priv; + + u8 AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; + u8 ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; + int TableLen; + + dprintk(1, "%s()\n", __func__); + + mxl5005s_reset(fe); + + /* Tuner initialization stage 0 */ + MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET); + AddrTable[0] = MASTER_CONTROL_ADDR; + ByteTable[0] |= state->config->AgcMasterByte; -int mxl5005s_init2(struct dvb_frontend *fe) + mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1); + + mxl5005s_AssignTunerMode(fe); // tunre_config + + /* Tuner initialization stage 1 */ + MXL_GetInitRegister(fe, AddrTable, ByteTable, &TableLen); + + mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); + + return 0; +} + +int mxl5005s_AssignTunerMode(struct dvb_frontend *fe) { - int MxlModMode; - int MxlIfMode; - unsigned long MxlBandwitdh; - unsigned long MxlIfFreqHz; - unsigned long MxlCrystalFreqHz; - int MxlAgcMode; - unsigned short MxlTop; - unsigned short MxlIfOutputLoad; - int MxlClockOut; - int MxlDivOut; - int MxlCapSel; - int MxlRssiOnOff; - unsigned char MxlStandard; - unsigned char MxlTfType; + struct mxl5005s_state *state = fe->tuner_priv; + struct mxl5005s_config *c = state->config; - /* Set MxL5005S parameters. */ - MxlModMode = MXL_DIGITAL_MODE; - MxlIfMode = MXL_ZERO_IF; -// steve - //MxlBandwitdh = MXL5005S_BANDWIDTH_8MHZ; - //MxlIfFreqHz = IF_FREQ_4570000HZ; - MxlBandwitdh = MXL5005S_BANDWIDTH_6MHZ; // config - MxlIfFreqHz = IF_FREQ_5380000HZ; // config - MxlCrystalFreqHz = CRYSTAL_FREQ_16000000HZ; // config - MxlAgcMode = MXL_SINGLE_AGC; - MxlTop = MXL5005S_TOP_25P2; - MxlIfOutputLoad = MXL5005S_IF_OUTPUT_LOAD_200_OHM; - MxlClockOut = MXL_CLOCK_OUT_DISABLE; - MxlDivOut = MXL_DIV_OUT_4; - MxlCapSel = MXL_CAP_SEL_ENABLE; - MxlRssiOnOff = MXL_RSSI_ENABLE; // config - MxlTfType = MXL_TF_C_H; // config - - MxlStandard = MXL_ATSC; // config - - // TODO: this is bad, it trashes other configs - // Set MxL5005S extra module. - //pExtra->AgcMasterByte = (MxlAgcMode == MXL_DUAL_AGC) ? 0x4 : 0x0; + InitTunerControls(fe); + /* Set MxL5005S parameters. */ MXL5005_TunerConfig( fe, - (unsigned char)MxlModMode, - (unsigned char)MxlIfMode, - MxlBandwitdh, - MxlIfFreqHz, - MxlCrystalFreqHz, - (unsigned char)MxlAgcMode, - MxlTop, - MxlIfOutputLoad, - (unsigned char)MxlClockOut, - (unsigned char)MxlDivOut, - (unsigned char)MxlCapSel, - (unsigned char)MxlRssiOnOff, - MxlStandard, MxlTfType); + c->mod_mode, + c->if_mode, + MXL5005S_BANDWIDTH_6MHZ, + c->if_freq, + c->xtal_freq, + c->agc_mode, + c->top, + c->output_load, + c->clock_out, + c->div_out, + c->cap_select, + c->rssi_enable, + MXL_QAM, + c->tracking_filter); return 0; } @@ -4609,7 +4533,11 @@ static int mxl5005s_set_params(struct dvb_frontend *fe, freq = params->frequency; /* Hz */ dprintk(1, "%s() freq=%d bw=%d\n", __func__, freq, bw); - return mxl5005s_SetRfFreqHz(fe, freq); + mxl5005s_SetRfFreqHz(fe, freq); + + msleep(350); + + return 0; } static int mxl5005s_get_frequency(struct dvb_frontend *fe, u32 *frequency) @@ -4642,32 +4570,6 @@ static int mxl5005s_get_status(struct dvb_frontend *fe, u32 *status) return 0; } -static int mxl5005s_init(struct dvb_frontend *fe) -{ - struct mxl5005s_state *state = fe->tuner_priv; - u8 AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; - u8 ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; - int TableLen; - - dprintk(1, "%s()\n", __func__); - - /* Initialize MxL5005S tuner according to MxL5005S tuner example code. */ - - /* Tuner initialization stage 0 */ - MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET); - AddrTable[0] = MASTER_CONTROL_ADDR; - ByteTable[0] |= state->config->AgcMasterByte; - - mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1); - - /* Tuner initialization stage 1 */ - MXL_GetInitRegister(fe, AddrTable, ByteTable, &TableLen); - - mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); - - return mxl5005s_init2(fe); -} - static int mxl5005s_release(struct dvb_frontend *fe) { dprintk(1, "%s()\n", __func__); diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h index 1c4d9da..2777ecc 100644 --- a/drivers/media/common/tuners/mxl5005s.h +++ b/drivers/media/common/tuners/mxl5005s.h @@ -26,31 +26,88 @@ #ifndef __MXL5005S_H #define __MXL5005S_H -/* IF frequency */ -enum IF_FREQ_HZ -{ - IF_FREQ_4570000HZ = 4570000, ///< IF frequency = 4.57 MHz - IF_FREQ_4571429HZ = 4571429, ///< IF frequency = 4.571 MHz - IF_FREQ_5380000HZ = 5380000, ///< IF frequency = 5.38 MHz - IF_FREQ_36000000HZ = 36000000, ///< IF frequency = 36.000 MHz - IF_FREQ_36125000HZ = 36125000, ///< IF frequency = 36.125 MHz - IF_FREQ_36166667HZ = 36166667, ///< IF frequency = 36.167 MHz - IF_FREQ_44000000HZ = 44000000, ///< IF frequency = 44.000 MHz -}; - -/* Crystal frequency */ -enum CRYSTAL_FREQ_HZ -{ - CRYSTAL_FREQ_4000000HZ = 4000000, ///< Crystal frequency = 4.0 MHz - CRYSTAL_FREQ_16000000HZ = 16000000, ///< Crystal frequency = 16.0 MHz - CRYSTAL_FREQ_25000000HZ = 25000000, ///< Crystal frequency = 25.0 MHz - CRYSTAL_FREQ_28800000HZ = 28800000, ///< Crystal frequency = 28.8 MHz -}; - struct mxl5005s_config { + /* 7 bit i2c address */ u8 i2c_address; +#define IF_FREQ_4570000HZ 4570000 +#define IF_FREQ_4571429HZ 4571429 +#define IF_FREQ_5380000HZ 5380000 +#define IF_FREQ_36000000HZ 36000000 +#define IF_FREQ_36125000HZ 36125000 +#define IF_FREQ_36166667HZ 36166667 +#define IF_FREQ_44000000HZ 44000000 + u32 if_freq; + +#define CRYSTAL_FREQ_4000000HZ 4000000 +#define CRYSTAL_FREQ_16000000HZ 16000000 +#define CRYSTAL_FREQ_25000000HZ 25000000 +#define CRYSTAL_FREQ_28800000HZ 28800000 + u32 xtal_freq; + +#define MXL_DUAL_AGC 0 +#define MXL_SINGLE_AGC 1 + u8 agc_mode; + +#define MXL_TF_DEFAULT 0 +#define MXL_TF_OFF 1 +#define MXL_TF_C 2 +#define MXL_TF_C_H 3 +#define MXL_TF_D 4 +#define MXL_TF_D_L 5 +#define MXL_TF_E 6 +#define MXL_TF_F 7 +#define MXL_TF_E_2 8 +#define MXL_TF_E_NA 9 +#define MXL_TF_G 10 + u8 tracking_filter; + +#define MXL_RSSI_DISABLE 0 +#define MXL_RSSI_ENABLE 1 + u8 rssi_enable; + +#define MXL_CAP_SEL_DISABLE 0 +#define MXL_CAP_SEL_ENABLE 1 + u8 cap_select; + +#define MXL_DIV_OUT_1 0 +#define MXL_DIV_OUT_4 1 + u8 div_out; + +#define MXL_CLOCK_OUT_DISABLE 0 +#define MXL_CLOCK_OUT_ENABLE 1 + u8 clock_out; + +#define MXL5005S_IF_OUTPUT_LOAD_200_OHM 200 +#define MXL5005S_IF_OUTPUT_LOAD_300_OHM 300 + u32 output_load; + +#define MXL5005S_TOP_5P5 55 +#define MXL5005S_TOP_7P2 72 +#define MXL5005S_TOP_9P2 92 +#define MXL5005S_TOP_11P0 110 +#define MXL5005S_TOP_12P9 129 +#define MXL5005S_TOP_14P7 147 +#define MXL5005S_TOP_16P8 168 +#define MXL5005S_TOP_19P4 194 +#define MXL5005S_TOP_21P2 212 +#define MXL5005S_TOP_23P2 232 +#define MXL5005S_TOP_25P2 252 +#define MXL5005S_TOP_27P1 271 +#define MXL5005S_TOP_29P2 292 +#define MXL5005S_TOP_31P7 317 +#define MXL5005S_TOP_34P9 349 + u32 top; + +#define MXL_ANALOG_MODE 0 +#define MXL_DIGITAL_MODE 1 + u8 mod_mode; + +#define MXL_ZERO_IF 0 +#define MXL_LOW_IF 1 + u8 if_mode; + /* Stuff I don't know what to do with */ u8 AgcMasterByte; }; -- cgit v1.1 From 7f5c3affef2883f49e820db62413e1dff1d4cebb Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 1 May 2008 06:51:36 -0300 Subject: V4L/DVB(7869): mxl5005s: Cleanup #6 Cleanup #6 Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 414 ++++++++++++++++++--------------- drivers/media/common/tuners/mxl5005s.h | 48 ++-- 2 files changed, 248 insertions(+), 214 deletions(-) diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index aad88d5..f7ed9a72 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -1,26 +1,62 @@ /* - * For the Realtek RTL chip RTL2831U - * Realtek Release Date: 2008-03-14, ver 080314 - * Realtek version RTL2831 Linux driver version 080314 - * ver 080314 - * - * for linux kernel version 2.6.21.4 - 2.6.22-14 - * support MXL5005s and MT2060 tuners (support tuner auto-detecting) - * support two IR types -- RC5 and NEC - * - * Known boards with Realtek RTL chip RTL2821U - * Freecom USB stick 14aa:0160 (version 4) - * Conceptronic CTVDIGRCU - * - * Copyright (c) 2008 Realtek - * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper - * This code is placed under the terms of the GNU General Public License - * - * Released by Realtek under GPLv2. - * Thanks to Realtek for a lot of support we received ! - * - * Revision: 080314 - original version - */ + MaxLinear MXL5005S VSB/QAM/DVBT tuner driver + + Copyright (C) 2008 MaxLinear + Copyright (C) 2006 Steven Toth + Functions: + mxl5005s_reset() + mxl5005s_writereg() + mxl5005s_writeregs() + mxl5005s_init() + mxl5005s_reconfigure() + mxl5005s_AssignTunerMode() + mxl5005s_set_params() + mxl5005s_get_frequency() + mxl5005s_get_bandwidth() + mxl5005s_release() + mxl5005s_attach() + + Copyright (c) 2008 Realtek + Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper + Functions: + mxl5005s_SetRfFreqHz() + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/* + History of this driver (Steven Toth): + I was given a public release of a linux driver that included + support for the MaxLinear MXL5005S silicon tuner. Analysis of + the tuner driver showed clearly three things. + + 1. The tuner driver didn't support the LinuxTV tuner API + so the code Realtek added had to be removed. + + 2. A significant amount of the driver is reference driver code + from MaxLinear, I felt it was important to identify and + preserve this. + + 3. New code has to be added to interface correctly with the + LinuxTV API, as a regular kernel module. + + Other than the reference driver enum's, I've clearly marked + sections of the code and retained the copyright of the + respective owners. +*/ #include "mxl5005s.h" @@ -250,9 +286,12 @@ struct mxl5005s_state struct mxl5005s_config *config; struct dvb_frontend *frontend; struct i2c_adapter *i2c; + + /* Cache values */ + u32 current_mode; + }; -// funcs u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value); u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value); u16 MXL_GetMasterControl(u8 *MasterReg, int state); @@ -269,9 +308,22 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq); void MXL_SynthIFLO_Calc(struct dvb_frontend *fe); void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe); u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count); -int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen); +int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, u8 len); u16 MXL_IFSynthInit(struct dvb_frontend *fe); -int mxl5005s_AssignTunerMode(struct dvb_frontend *fe); +int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth); +int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth); + +/* ---------------------------------------------------------------- + * Begin: Custom code salvaged from the Realtek driver. + * Copyright (c) 2008 Realtek + * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper + * This code is placed under the terms of the GNU General Public License + * + * Released by Realtek under GPLv2. + * Thanks to Realtek for a lot of support we received ! + * + * Revision: 080314 - original version + */ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) { @@ -292,7 +344,7 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) AddrTable[0] = MASTER_CONTROL_ADDR; ByteTable[0] |= state->config->AgcMasterByte; - mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1); + mxl5005s_writeregs(fe, AddrTable, ByteTable, 1); // Tuner RF frequency setting stage 1 MXL_TuneRF(fe, RfFreqHz); @@ -309,7 +361,7 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte; TableLen += 1; - mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); + mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen); // Wait 30 ms. msleep(150); @@ -324,118 +376,18 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte ; TableLen += 1; - mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); + mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen); msleep(100); return 0; } +/* End: Custom code taken from the Realtek driver */ -static int mxl5005s_reset(struct dvb_frontend *fe) -{ - struct mxl5005s_state *state = fe->tuner_priv; - int ret = 0; - - u8 buf[2] = { 0xff, 0x00 }; - struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, - .buf = buf, .len = 2 }; - - dprintk(2, "%s()\n", __func__); - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - - if (i2c_transfer(state->i2c, &msg, 1) != 1) { - printk(KERN_WARNING "mxl5005s I2C reset failed\n"); - ret = -EREMOTEIO; - } - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); - - return ret; -} - -/* Write a single byte to a single reg */ -static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val, int latch) -{ - struct mxl5005s_state *state = fe->tuner_priv; - u8 buf[3] = { reg, val, MXL5005S_LATCH_BYTE }; - struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, - .buf = buf, .len = 3 }; - - if(latch == 0) - msg.len = 2; - - dprintk(2, "%s(reg = 0x%x val = 0x%x addr = 0x%x)\n", __func__, reg, val, msg.addr); - - if (i2c_transfer(state->i2c, &msg, 1) != 1) { - printk(KERN_WARNING "mxl5005s I2C write failed\n"); - return -EREMOTEIO; - } - return 0; -} - -int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen) -{ - int i, ret = 0; - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - - for( i = 0 ; i < TableLen - 1 ; i++) - { - ret = mxl5005s_writereg(fe, pAddrTable[i], pByteTable[i], 0); - if (ret < 0) - break; - } - - ret = mxl5005s_writereg(fe, pAddrTable[i], pByteTable[i], 1); - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); - - return ret; -} - -int mxl5005s_SetRegMaskBits(struct dvb_frontend *fe, - unsigned char RegAddr, - unsigned char Msb, - unsigned char Lsb, - const unsigned char WritingValue - ) -{ - int i; - - unsigned char Mask; - unsigned char Shift; - unsigned char RegByte; - - /* Generate mask and shift according to MSB and LSB. */ - Mask = 0; - for(i = Lsb; i < (unsigned char)(Msb + 1); i++) - Mask |= 0x1 << i; - - Shift = Lsb; - - /* Get tuner register byte according to register adddress. */ - MXL_RegRead(fe, RegAddr, &RegByte); - - /* Reserve register byte unmask bit with mask and inlay writing value into it. */ - RegByte &= ~Mask; - RegByte |= (WritingValue << Shift) & Mask; - - /* Update tuner register byte table. */ - MXL_RegWrite(fe, RegAddr, RegByte); - - /* Write tuner register byte with writing byte. */ - return mxl5005s_SetRegsWithTable(fe, &RegAddr, &RegByte, 1); -} - - -// The following context is source code provided by MaxLinear. -// MaxLinear source code - MXL5005_Initialize.cpp -// DONE +/* ---------------------------------------------------------------- + * Begin: Reference driver code found in the Realtek driver. + * Copyright (c) 2008 MaxLinear + */ u16 MXL5005_RegisterInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -757,7 +709,6 @@ u16 MXL5005_RegisterInit(struct dvb_frontend *fe) return 0 ; } -// DONE u16 MXL5005_ControlInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -1701,7 +1652,6 @@ u16 MXL5005_ControlInit(struct dvb_frontend *fe) // MaxLinear source code - MXL5005_c.cpp // MXL5005.cpp : Defines the initialization routines for the DLL. // 2.6.12 -// DONE void InitTunerControls(struct dvb_frontend *fe) { MXL5005_RegisterInit(fe); @@ -1744,7 +1694,6 @@ void InitTunerControls(struct dvb_frontend *fe) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL5005_TunerConfig(struct dvb_frontend *fe, u8 Mode, /* 0: Analog Mode ; 1: Digital Mode */ u8 IF_mode, /* for Analog Mode, 0: zero IF; 1: low IF */ @@ -1814,7 +1763,6 @@ u16 MXL5005_TunerConfig(struct dvb_frontend *fe, // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -// DONE void MXL_SynthIFLO_Calc(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -1853,7 +1801,6 @@ void MXL_SynthIFLO_Calc(struct dvb_frontend *fe) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -// DONE void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -1892,7 +1839,6 @@ void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) { u16 status = 0; @@ -1930,7 +1876,6 @@ u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_BlockInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -3687,7 +3632,6 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) return status ; } -// DONE u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val) { u16 status = 0; @@ -3754,7 +3698,6 @@ u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val) // >0 : Value exceed maximum allowed for control number // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value) { u16 status = 0; @@ -3795,7 +3738,6 @@ u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value) // 2 : Control name not found // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u16 controlGroup) { struct mxl5005s_state *state = fe->tuner_priv; @@ -3902,7 +3844,6 @@ u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u // -1 : Invalid Register Address // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) { struct mxl5005s_state *state = fe->tuner_priv; @@ -3942,7 +3883,6 @@ u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) // -1 : Invalid Register Address // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) { struct mxl5005s_state *state = fe->tuner_priv; @@ -3979,7 +3919,6 @@ u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) // -1 : Invalid control name // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4051,7 +3990,6 @@ u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value) // -1 : Invalid control name // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int * count) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4157,7 +4095,6 @@ u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int // NONE // // // /////////////////////////////////////////////////////////////////////////////// -// DONE void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4205,7 +4142,6 @@ void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal) // Computed value // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u32 MXL_Ceiling(u32 value, u32 resolution) { return (value/resolution + (value % resolution > 0 ? 1 : 0)); @@ -4214,7 +4150,6 @@ u32 MXL_Ceiling(u32 value, u32 resolution) // // Retrieve the Initialzation Registers // -// DONE u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { u16 status = 0; @@ -4237,7 +4172,6 @@ u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *c return status; } -// DONE u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { u16 status = 0; @@ -4265,7 +4199,6 @@ u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *cou return status; } -// DONE u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { u16 status = 0; @@ -4283,7 +4216,6 @@ u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, i return status; } -// DONE u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { u16 status = 0; @@ -4301,7 +4233,6 @@ u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, in return status; } -// DONE u16 MXL_GetMasterControl(u8 *MasterReg, int state) { if (state == 1) /* Load_Start */ @@ -4446,7 +4377,6 @@ u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range) return status; } -// DONE u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4457,20 +4387,99 @@ u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis) return status; } - #endif +/* End: Reference driver code found in the Realtek driver that + * is copyright MaxLinear */ + +/* ---------------------------------------------------------------- + * Begin: Everything after here is new code to adapt the + * proprietary Realtek driver into a Linux API tuner. + * Copyright (C) 2008 Steven Toth + */ +static int mxl5005s_reset(struct dvb_frontend *fe) +{ + struct mxl5005s_state *state = fe->tuner_priv; + int ret = 0; + + u8 buf[2] = { 0xff, 0x00 }; + struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, + .buf = buf, .len = 2 }; + + dprintk(2, "%s()\n", __func__); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + printk(KERN_WARNING "mxl5005s I2C reset failed\n"); + ret = -EREMOTEIO; + } + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return ret; +} + +/* Write a single byte to a single reg, latch the value if required by + * following the transaction with the latch byte. + */ +static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val, int latch) +{ + struct mxl5005s_state *state = fe->tuner_priv; + u8 buf[3] = { reg, val, MXL5005S_LATCH_BYTE }; + struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, + .buf = buf, .len = 3 }; + + if (latch == 0) + msg.len = 2; + + dprintk(2, "%s(reg = 0x%x val = 0x%x addr = 0x%x)\n", __func__, reg, val, msg.addr); + + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + printk(KERN_WARNING "mxl5005s I2C write failed\n"); + return -EREMOTEIO; + } + return 0; +} + +int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, u8 len) +{ + int ret = 0, i; + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); + + for (i = 0 ; i < len-1; i++) { + ret = mxl5005s_writereg(fe, addrtable[i], datatable[i], 0); + if (ret < 0) + break; + } + + ret = mxl5005s_writereg(fe, addrtable[i], datatable[i], 1); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return ret; +} -/* Linux driver related functions */ int mxl5005s_init(struct dvb_frontend *fe) { + dprintk(1, "%s()\n", __func__); + return mxl5005s_reconfigure(fe, MXL_QAM, MXL5005S_BANDWIDTH_6MHZ); +} + +int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth) +{ struct mxl5005s_state *state = fe->tuner_priv; u8 AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; u8 ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; int TableLen; - dprintk(1, "%s()\n", __func__); + dprintk(1, "%s(type=%d, bw=%d)\n", __func__, mod_type, bandwidth); mxl5005s_reset(fe); @@ -4479,19 +4488,19 @@ int mxl5005s_init(struct dvb_frontend *fe) AddrTable[0] = MASTER_CONTROL_ADDR; ByteTable[0] |= state->config->AgcMasterByte; - mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1); + mxl5005s_writeregs(fe, AddrTable, ByteTable, 1); - mxl5005s_AssignTunerMode(fe); // tunre_config + mxl5005s_AssignTunerMode(fe, mod_type, bandwidth); /* Tuner initialization stage 1 */ MXL_GetInitRegister(fe, AddrTable, ByteTable, &TableLen); - mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); + mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen); return 0; } -int mxl5005s_AssignTunerMode(struct dvb_frontend *fe) +int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth) { struct mxl5005s_state *state = fe->tuner_priv; struct mxl5005s_config *c = state->config; @@ -4503,7 +4512,7 @@ int mxl5005s_AssignTunerMode(struct dvb_frontend *fe) fe, c->mod_mode, c->if_mode, - MXL5005S_BANDWIDTH_6MHZ, + bandwidth, c->if_freq, c->xtal_freq, c->agc_mode, @@ -4513,7 +4522,7 @@ int mxl5005s_AssignTunerMode(struct dvb_frontend *fe) c->div_out, c->cap_select, c->rssi_enable, - MXL_QAM, + mod_type, c->tracking_filter); return 0; @@ -4522,22 +4531,62 @@ int mxl5005s_AssignTunerMode(struct dvb_frontend *fe) static int mxl5005s_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *params) { - u32 freq; - u32 bw; + struct mxl5005s_state *state = fe->tuner_priv; + u32 req_mode, req_bw = 0; + int ret; - if (fe->ops.info.type == FE_OFDM) - bw = params->u.ofdm.bandwidth; - else - bw = MXL5005S_BANDWIDTH_6MHZ; + dprintk(1, "%s()\n", __func__); + + if (fe->ops.info.type == FE_ATSC) { + switch (params->u.vsb.modulation) { + case VSB_8: + req_mode = MXL_ATSC; break; + default: + case QAM_64: + case QAM_256: + case QAM_AUTO: + req_mode = MXL_QAM; break; + } + } + else req_mode = MXL_DVBT; + + /* Change tuner for new modulation type if reqd */ + if (req_mode != state->current_mode) { + switch (req_mode) { + case VSB_8: + case QAM_64: + case QAM_256: + case QAM_AUTO: + req_bw = MXL5005S_BANDWIDTH_6MHZ; + break; + default: + /* Assume DVB-T */ + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + req_bw = MXL5005S_BANDWIDTH_6MHZ; + break; + case BANDWIDTH_7_MHZ: + req_bw = MXL5005S_BANDWIDTH_7MHZ; + break; + case BANDWIDTH_AUTO: + case BANDWIDTH_8_MHZ: + req_bw = MXL5005S_BANDWIDTH_8MHZ; + break; + } + } - freq = params->frequency; /* Hz */ - dprintk(1, "%s() freq=%d bw=%d\n", __func__, freq, bw); + state->current_mode = req_mode; + ret = mxl5005s_reconfigure(fe, req_mode, req_bw); - mxl5005s_SetRfFreqHz(fe, freq); + } else + ret = 0; - msleep(350); + if (ret == 0) { + dprintk(1, "%s() freq=%d\n", __func__, params->frequency); + ret = mxl5005s_SetRfFreqHz(fe, params->frequency); + } - return 0; + return ret; } static int mxl5005s_get_frequency(struct dvb_frontend *fe, u32 *frequency) @@ -4560,16 +4609,6 @@ static int mxl5005s_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) return 0; } -static int mxl5005s_get_status(struct dvb_frontend *fe, u32 *status) -{ - dprintk(1, "%s()\n", __func__); - - *status = 0; - // *status = TUNER_STATUS_LOCKED; - - return 0; -} - static int mxl5005s_release(struct dvb_frontend *fe) { dprintk(1, "%s()\n", __func__); @@ -4592,7 +4631,6 @@ static const struct dvb_tuner_ops mxl5005s_tuner_ops = { .set_params = mxl5005s_set_params, .get_frequency = mxl5005s_get_frequency, .get_bandwidth = mxl5005s_get_bandwidth, - .get_status = mxl5005s_get_status }; struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, @@ -4609,6 +4647,7 @@ struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, state->frontend = fe; state->config = config; state->i2c = i2c; + state->current_mode = MXL_QAM; printk(KERN_INFO "MXL5005S: Attached at address 0x%02x\n", config->i2c_address); @@ -4620,8 +4659,5 @@ struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, EXPORT_SYMBOL(mxl5005s_attach); MODULE_DESCRIPTION("MaxLinear MXL5005S silicon tuner driver"); -MODULE_AUTHOR("Jan Hoogenraad"); -MODULE_AUTHOR("Barnaby Shearer"); -MODULE_AUTHOR("Andy Hasper"); MODULE_AUTHOR("Steven Toth"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h index 2777ecc..7658401 100644 --- a/drivers/media/common/tuners/mxl5005s.h +++ b/drivers/media/common/tuners/mxl5005s.h @@ -1,27 +1,24 @@ /* - * For the Realtek RTL chip RTL2831U - * Realtek Release Date: 2008-03-14, ver 080314 - * Realtek version RTL2831 Linux driver version 080314 - * ver 080314 - * - * for linux kernel version 2.6.21.4 - 2.6.22-14 - * support MXL5005s and MT2060 tuners (support tuner auto-detecting) - * support two IR types -- RC5 and NEC - * - * Known boards with Realtek RTL chip RTL2821U - * Freecom USB stick 14aa:0160 (version 4) - * Conceptronic CTVDIGRCU - * - * Copyright (c) 2008 Realtek - * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper - * This code is placed under the terms of the GNU General Public License - * - * Released by Realtek under GPLv2. - * Thanks to Realtek for a lot of support we received ! - * - * Revision: 080314 - original version - */ + MaxLinear MXL5005S VSB/QAM/DVBT tuner driver + Copyright (C) 2008 MaxLinear + Copyright (C) 2008 Steven Toth + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ #ifndef __MXL5005S_H #define __MXL5005S_H @@ -112,14 +109,15 @@ struct mxl5005s_config u8 AgcMasterByte; }; -#if defined(CONFIG_DVB_TUNER_MXL5005S) || (defined(CONFIG_DVB_TUNER_MXL5005S_MODULE) && defined(MODULE)) +#if defined(CONFIG_DVB_TUNER_MXL5005S) || \ + (defined(CONFIG_DVB_TUNER_MXL5005S_MODULE) && defined(MODULE)) extern struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, - struct mxl5005s_config *config); + struct mxl5005s_config *config) #else static inline struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, - struct mxl5005s_config *config); + struct mxl5005s_config *config) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; -- cgit v1.1 From 5c1b20514f592af19974166f130b85346c1fbf3a Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 1 May 2008 07:04:09 -0300 Subject: V4L/DVB (7870): mxl5005s: Basic digital support. ATSC and QAM should be working but basic testing is required. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 616 ++++++++++++++++++--------------- drivers/media/common/tuners/mxl5005s.h | 145 +++----- 2 files changed, 389 insertions(+), 372 deletions(-) diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index f7ed9a72..64aa864 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -1,69 +1,40 @@ /* - MaxLinear MXL5005S VSB/QAM/DVBT tuner driver - - Copyright (C) 2008 MaxLinear - Copyright (C) 2006 Steven Toth - Functions: - mxl5005s_reset() - mxl5005s_writereg() - mxl5005s_writeregs() - mxl5005s_init() - mxl5005s_reconfigure() - mxl5005s_AssignTunerMode() - mxl5005s_set_params() - mxl5005s_get_frequency() - mxl5005s_get_bandwidth() - mxl5005s_release() - mxl5005s_attach() - - Copyright (c) 2008 Realtek - Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper - Functions: - mxl5005s_SetRfFreqHz() - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -/* - History of this driver (Steven Toth): - I was given a public release of a linux driver that included - support for the MaxLinear MXL5005S silicon tuner. Analysis of - the tuner driver showed clearly three things. - - 1. The tuner driver didn't support the LinuxTV tuner API - so the code Realtek added had to be removed. - - 2. A significant amount of the driver is reference driver code - from MaxLinear, I felt it was important to identify and - preserve this. - - 3. New code has to be added to interface correctly with the - LinuxTV API, as a regular kernel module. - - Other than the reference driver enum's, I've clearly marked - sections of the code and retained the copyright of the - respective owners. -*/ + * For the Realtek RTL chip RTL2831U + * Realtek Release Date: 2008-03-14, ver 080314 + * Realtek version RTL2831 Linux driver version 080314 + * ver 080314 + * + * for linux kernel version 2.6.21.4 - 2.6.22-14 + * support MXL5005s and MT2060 tuners (support tuner auto-detecting) + * support two IR types -- RC5 and NEC + * + * Known boards with Realtek RTL chip RTL2821U + * Freecom USB stick 14aa:0160 (version 4) + * Conceptronic CTVDIGRCU + * + * Copyright (c) 2008 Realtek + * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper + * This code is placed under the terms of the GNU General Public License + * + * Released by Realtek under GPLv2. + * Thanks to Realtek for a lot of support we received ! + * + * Revision: 080314 - original version + */ +#include +#include +#include +#include +#include +#include +#include "dvb_frontend.h" #include "mxl5005s.h" -static int debug = 2; +static int debug; #define dprintk(level, arg...) do { \ - if (level <= debug) \ + if (debug >= level) \ printk(arg); \ } while (0) @@ -79,6 +50,13 @@ static int debug = 2; #define MXLCTRL_NUM 189 #define MASTER_CONTROL_ADDR 9 +/* Enumeration of AGC Mode */ +typedef enum +{ + MXL_DUAL_AGC = 0, + MXL_SINGLE_AGC +} AGC_Mode; + /* Enumeration of Master Control Register State */ typedef enum { @@ -88,6 +66,51 @@ typedef enum MC_SEQ_OFF } Master_Control_State; +/* Enumeration of MXL5005 Tuner Mode */ +typedef enum +{ + MXL_ANALOG_MODE = 0, + MXL_DIGITAL_MODE +} Tuner_Mode; + +/* Enumeration of MXL5005 Tuner IF Mode */ +typedef enum +{ + MXL_ZERO_IF = 0, + MXL_LOW_IF +} Tuner_IF_Mode; + +/* Enumeration of MXL5005 Tuner Clock Out Mode */ +typedef enum +{ + MXL_CLOCK_OUT_DISABLE = 0, + MXL_CLOCK_OUT_ENABLE +} Tuner_Clock_Out; + +/* Enumeration of MXL5005 Tuner Div Out Mode */ +typedef enum +{ + MXL_DIV_OUT_1 = 0, + MXL_DIV_OUT_4 + +} Tuner_Div_Out; + +/* Enumeration of MXL5005 Tuner Pull-up Cap Select Mode */ +typedef enum +{ + MXL_CAP_SEL_DISABLE = 0, + MXL_CAP_SEL_ENABLE + +} Tuner_Cap_Select; + +/* Enumeration of MXL5005 Tuner RSSI Mode */ +typedef enum +{ + MXL_RSSI_DISABLE = 0, + MXL_RSSI_ENABLE + +} Tuner_RSSI; + /* Enumeration of MXL5005 Tuner Modulation Type */ typedef enum { @@ -99,6 +122,22 @@ typedef enum MXL_ANALOG_OTA } Tuner_Modu_Type; +/* Enumeration of MXL5005 Tuner Tracking Filter Type */ +typedef enum +{ + MXL_TF_DEFAULT = 0, + MXL_TF_OFF, + MXL_TF_C, + MXL_TF_C_H, + MXL_TF_D, + MXL_TF_D_L, + MXL_TF_E, + MXL_TF_F, + MXL_TF_E_2, + MXL_TF_E_NA, + MXL_TF_G +} Tuner_TF_Type; + /* MXL5005 Tuner Register Struct */ typedef struct _TunerReg_struct { @@ -229,6 +268,33 @@ enum }; #define MXL5005S_BANDWIDTH_MODE_NUM 3 +/* Top modes */ +enum +{ + MXL5005S_TOP_5P5 = 55, + MXL5005S_TOP_7P2 = 72, + MXL5005S_TOP_9P2 = 92, + MXL5005S_TOP_11P0 = 110, + MXL5005S_TOP_12P9 = 129, + MXL5005S_TOP_14P7 = 147, + MXL5005S_TOP_16P8 = 168, + MXL5005S_TOP_19P4 = 194, + MXL5005S_TOP_21P2 = 212, + MXL5005S_TOP_23P2 = 232, + MXL5005S_TOP_25P2 = 252, + MXL5005S_TOP_27P1 = 271, + MXL5005S_TOP_29P2 = 292, + MXL5005S_TOP_31P7 = 317, + MXL5005S_TOP_34P9 = 349, +}; + +/* IF output load */ +enum +{ + MXL5005S_IF_OUTPUT_LOAD_200_OHM = 200, + MXL5005S_IF_OUTPUT_LOAD_300_OHM = 300, +}; + /* MXL5005 Tuner Control Struct */ typedef struct _TunerControl_struct { u16 Ctrl_Num; /* Control Number */ @@ -283,15 +349,13 @@ struct mxl5005s_state TunerRegs[TUNER_REGS_NUM]; /* Tuner Register Array Pointer */ /* Linux driver framework specific */ - struct mxl5005s_config *config; + const struct mxl5005s_config *config; + struct dvb_frontend *frontend; struct i2c_adapter *i2c; - - /* Cache values */ - u32 current_mode; - }; +// funcs u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value); u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value); u16 MXL_GetMasterControl(u8 *MasterReg, int state); @@ -308,26 +372,14 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq); void MXL_SynthIFLO_Calc(struct dvb_frontend *fe); void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe); u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count); -int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, u8 len); +int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen); u16 MXL_IFSynthInit(struct dvb_frontend *fe); -int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth); -int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth); - -/* ---------------------------------------------------------------- - * Begin: Custom code salvaged from the Realtek driver. - * Copyright (c) 2008 Realtek - * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper - * This code is placed under the terms of the GNU General Public License - * - * Released by Realtek under GPLv2. - * Thanks to Realtek for a lot of support we received ! - * - * Revision: 080314 - original version - */ +static int mxl5005s_init2(struct dvb_frontend *fe); int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) { struct mxl5005s_state *state = fe->tuner_priv; + u8 AgcMasterByte = state->config->AgcMasterByte; unsigned char AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; unsigned char ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; int TableLen; @@ -344,7 +396,7 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) AddrTable[0] = MASTER_CONTROL_ADDR; ByteTable[0] |= state->config->AgcMasterByte; - mxl5005s_writeregs(fe, AddrTable, ByteTable, 1); + mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1); // Tuner RF frequency setting stage 1 MXL_TuneRF(fe, RfFreqHz); @@ -358,13 +410,13 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ; AddrTable[TableLen] = MASTER_CONTROL_ADDR ; - ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte; + ByteTable[TableLen] = MasterControlByte | AgcMasterByte; TableLen += 1; - mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen); + mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); // Wait 30 ms. - msleep(150); + msleep(30); // Tuner RF frequency setting stage 2 MXL_ControlWrite(fe, SEQ_FSM_PULSE, 1) ; @@ -373,21 +425,101 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ; AddrTable[TableLen] = MASTER_CONTROL_ADDR ; - ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte ; + ByteTable[TableLen] = MasterControlByte | AgcMasterByte ; TableLen += 1; - mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen); + mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); - msleep(100); + return 0; +} +/* Write a single byte to a single reg */ +static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val) +{ + struct mxl5005s_state *state = fe->tuner_priv; + u8 buf[2] = { reg, val }; + struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, + .buf = buf, .len = 2 }; + + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + printk(KERN_WARNING "mxl5005s I2C write failed\n"); + return -EREMOTEIO; + } return 0; } -/* End: Custom code taken from the Realtek driver */ -/* ---------------------------------------------------------------- - * Begin: Reference driver code found in the Realtek driver. - * Copyright (c) 2008 MaxLinear - */ +/* Write a word to a single reg */ +static int mxl5005s_writereg16(struct dvb_frontend *fe, u8 reg, u16 val) +{ + struct mxl5005s_state *state = fe->tuner_priv; + u8 buf[3] = { reg, val >> 8 , val & 0xff }; + struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, + .buf = buf, .len = 3 }; + + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + printk(KERN_WARNING "mxl5005s I2C write16 failed\n"); + return -EREMOTEIO; + } + return 0; +} + +int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen) +{ + int i, ret; + u8 end_two_bytes_buf[]={ 0 , 0 }; + + for( i = 0 ; i < TableLen - 1 ; i++) + { + ret = mxl5005s_writereg(fe, pAddrTable[i], pByteTable[i]); + if (!ret) + return ret; + } + + end_two_bytes_buf[0] = pByteTable[i]; + end_two_bytes_buf[1] = MXL5005S_LATCH_BYTE; + + ret = mxl5005s_writereg16(fe, pAddrTable[i], (end_two_bytes_buf[0] << 8) | end_two_bytes_buf[1]); + + return ret; +} + +int mxl5005s_SetRegMaskBits(struct dvb_frontend *fe, + unsigned char RegAddr, + unsigned char Msb, + unsigned char Lsb, + const unsigned char WritingValue + ) +{ + int i; + + unsigned char Mask; + unsigned char Shift; + unsigned char RegByte; + + /* Generate mask and shift according to MSB and LSB. */ + Mask = 0; + for(i = Lsb; i < (unsigned char)(Msb + 1); i++) + Mask |= 0x1 << i; + + Shift = Lsb; + + /* Get tuner register byte according to register adddress. */ + MXL_RegRead(fe, RegAddr, &RegByte); + + /* Reserve register byte unmask bit with mask and inlay writing value into it. */ + RegByte &= ~Mask; + RegByte |= (WritingValue << Shift) & Mask; + + /* Update tuner register byte table. */ + MXL_RegWrite(fe, RegAddr, RegByte); + + /* Write tuner register byte with writing byte. */ + return mxl5005s_SetRegsWithTable(fe, &RegAddr, &RegByte, 1); +} + +// The following context is source code provided by MaxLinear. +// MaxLinear source code - MXL5005_Initialize.cpp +// DONE u16 MXL5005_RegisterInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -709,6 +841,7 @@ u16 MXL5005_RegisterInit(struct dvb_frontend *fe) return 0 ; } +// DONE u16 MXL5005_ControlInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -1652,6 +1785,7 @@ u16 MXL5005_ControlInit(struct dvb_frontend *fe) // MaxLinear source code - MXL5005_c.cpp // MXL5005.cpp : Defines the initialization routines for the DLL. // 2.6.12 +// DONE void InitTunerControls(struct dvb_frontend *fe) { MXL5005_RegisterInit(fe); @@ -1694,6 +1828,7 @@ void InitTunerControls(struct dvb_frontend *fe) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// +// DONE u16 MXL5005_TunerConfig(struct dvb_frontend *fe, u8 Mode, /* 0: Analog Mode ; 1: Digital Mode */ u8 IF_mode, /* for Analog Mode, 0: zero IF; 1: low IF */ @@ -1763,6 +1898,7 @@ u16 MXL5005_TunerConfig(struct dvb_frontend *fe, // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// +// DONE void MXL_SynthIFLO_Calc(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -1801,6 +1937,7 @@ void MXL_SynthIFLO_Calc(struct dvb_frontend *fe) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// +// DONE void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -1839,6 +1976,7 @@ void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// +// DONE u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) { u16 status = 0; @@ -1876,6 +2014,7 @@ u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// +// DONE u16 MXL_BlockInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -1903,7 +2042,6 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 2); break; case 6000000: - printk("%s() doing 6MHz digital\n", __func__); status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 3); break; } @@ -1934,6 +2072,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) else /* Single AGC Mode Dig Ana */ status += MXL_ControlWrite(fe, AGC_RF, state->Mode ? 15 : 12); + if (state->TOP == 55) /* TOP == 5.5 */ status += MXL_ControlWrite(fe, AGC_IF, 0x0); @@ -2163,8 +2302,6 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) status += MXL_ControlWrite(fe, BB_IQSWAP, 0); else /* High IF */ status += MXL_ControlWrite(fe, BB_IQSWAP, 1); - status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 2); - } if (state->Mod_Type == MXL_ANALOG_CABLE) { /* Analog Cable Mode */ @@ -2201,7 +2338,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) } /* RSSI disable */ - if(state->EN_RSSI == 0) { + if(state->EN_RSSI==0) { status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1); status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1); status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0); @@ -2410,7 +2547,6 @@ u16 MXL_IFSynthInit(struct dvb_frontend *fe) Fref = 324000000UL ; } if (state->IF_LO == 5380000UL) { - printk("%s() doing 5.38\n", __func__); status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 322800000UL ; @@ -3093,7 +3229,6 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) if (state->TF_Type == MXL_TF_C_H) // Tracking Filter type C-H for Hauppauge only { - printk("%s() CH filter\n", __func__); status += MXL_ControlWrite(fe, DAC_DIN_A, 0) ; if (state->RF_IN >= 43000000 && state->RF_IN < 150000000) @@ -3632,6 +3767,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) return status ; } +// DONE u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val) { u16 status = 0; @@ -3698,6 +3834,7 @@ u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val) // >0 : Value exceed maximum allowed for control number // // // /////////////////////////////////////////////////////////////////////////////// +// DONE u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value) { u16 status = 0; @@ -3738,6 +3875,7 @@ u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value) // 2 : Control name not found // // // /////////////////////////////////////////////////////////////////////////////// +// DONE u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u16 controlGroup) { struct mxl5005s_state *state = fe->tuner_priv; @@ -3844,6 +3982,7 @@ u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u // -1 : Invalid Register Address // // // /////////////////////////////////////////////////////////////////////////////// +// DONE u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) { struct mxl5005s_state *state = fe->tuner_priv; @@ -3883,6 +4022,7 @@ u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) // -1 : Invalid Register Address // // // /////////////////////////////////////////////////////////////////////////////// +// DONE u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) { struct mxl5005s_state *state = fe->tuner_priv; @@ -3919,6 +4059,7 @@ u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) // -1 : Invalid control name // // // /////////////////////////////////////////////////////////////////////////////// +// DONE u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value) { struct mxl5005s_state *state = fe->tuner_priv; @@ -3990,6 +4131,7 @@ u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value) // -1 : Invalid control name // // // /////////////////////////////////////////////////////////////////////////////// +// DONE u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int * count) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4095,6 +4237,7 @@ u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int // NONE // // // /////////////////////////////////////////////////////////////////////////////// +// DONE void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4142,6 +4285,7 @@ void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal) // Computed value // // // /////////////////////////////////////////////////////////////////////////////// +// DONE u32 MXL_Ceiling(u32 value, u32 resolution) { return (value/resolution + (value % resolution > 0 ? 1 : 0)); @@ -4150,6 +4294,7 @@ u32 MXL_Ceiling(u32 value, u32 resolution) // // Retrieve the Initialzation Registers // +// DONE u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { u16 status = 0; @@ -4172,6 +4317,7 @@ u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *c return status; } +// DONE u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { u16 status = 0; @@ -4199,6 +4345,7 @@ u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *cou return status; } +// DONE u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { u16 status = 0; @@ -4216,6 +4363,7 @@ u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, i return status; } +// DONE u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { u16 status = 0; @@ -4233,6 +4381,7 @@ u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, in return status; } +// DONE u16 MXL_GetMasterControl(u8 *MasterReg, int state) { if (state == 1) /* Load_Start */ @@ -4377,6 +4526,7 @@ u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range) return status; } +// DONE u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4387,224 +4537,141 @@ u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis) return status; } + #endif -/* End: Reference driver code found in the Realtek driver that - * is copyright MaxLinear */ -/* ---------------------------------------------------------------- - * Begin: Everything after here is new code to adapt the - * proprietary Realtek driver into a Linux API tuner. - * Copyright (C) 2008 Steven Toth - */ -static int mxl5005s_reset(struct dvb_frontend *fe) +/* Linux driver related functions */ + + +int mxl5005s_init(struct dvb_frontend *fe) { - struct mxl5005s_state *state = fe->tuner_priv; - int ret = 0; + int MxlModMode; + int MxlIfMode; + unsigned long MxlBandwitdh; + unsigned long MxlIfFreqHz; + unsigned long MxlCrystalFreqHz; + int MxlAgcMode; + unsigned short MxlTop; + unsigned short MxlIfOutputLoad; + int MxlClockOut; + int MxlDivOut; + int MxlCapSel; + int MxlRssiOnOff; + unsigned char MxlStandard; + unsigned char MxlTfType; - u8 buf[2] = { 0xff, 0x00 }; - struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, - .buf = buf, .len = 2 }; + /* Set MxL5005S parameters. */ + MxlModMode = MXL_DIGITAL_MODE; + MxlIfMode = MXL_ZERO_IF; +// steve + //MxlBandwitdh = MXL5005S_BANDWIDTH_8MHZ; + //MxlIfFreqHz = IF_FREQ_4570000HZ; + MxlBandwitdh = MXL5005S_BANDWIDTH_6MHZ; // config + MxlIfFreqHz = IF_FREQ_5380000HZ; // config + MxlCrystalFreqHz = CRYSTAL_FREQ_16000000HZ; // config + MxlAgcMode = MXL_SINGLE_AGC; + MxlTop = MXL5005S_TOP_25P2; + MxlIfOutputLoad = MXL5005S_IF_OUTPUT_LOAD_200_OHM; + MxlClockOut = MXL_CLOCK_OUT_DISABLE; + MxlDivOut = MXL_DIV_OUT_4; + MxlCapSel = MXL_CAP_SEL_ENABLE; + MxlRssiOnOff = MXL_RSSI_ENABLE; // config + MxlTfType = MXL_TF_C_H; // config + + MxlStandard = MXL_ATSC; // config + + // TODO: this is bad, it trashes other configs + // Set MxL5005S extra module. + //pExtra->AgcMasterByte = (MxlAgcMode == MXL_DUAL_AGC) ? 0x4 : 0x0; - dprintk(2, "%s()\n", __func__); + MXL5005_TunerConfig( + fe, + (unsigned char)MxlModMode, + (unsigned char)MxlIfMode, + MxlBandwitdh, + MxlIfFreqHz, + MxlCrystalFreqHz, + (unsigned char)MxlAgcMode, + MxlTop, + MxlIfOutputLoad, + (unsigned char)MxlClockOut, + (unsigned char)MxlDivOut, + (unsigned char)MxlCapSel, + (unsigned char)MxlRssiOnOff, + MxlStandard, MxlTfType); + + return mxl5005s_init2(fe); +} - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); +static int mxl5005s_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + u32 freq; + u32 bw; - if (i2c_transfer(state->i2c, &msg, 1) != 1) { - printk(KERN_WARNING "mxl5005s I2C reset failed\n"); - ret = -EREMOTEIO; - } + if (fe->ops.info.type == FE_OFDM) + bw = params->u.ofdm.bandwidth; + else + bw = MXL5005S_BANDWIDTH_6MHZ; - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); + freq = params->frequency; /* Hz */ + dprintk(1, "%s() freq=%d bw=%d\n", __func__, freq, bw); - return ret; + return mxl5005s_SetRfFreqHz(fe, freq); } -/* Write a single byte to a single reg, latch the value if required by - * following the transaction with the latch byte. - */ -static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val, int latch) +static int mxl5005s_get_frequency(struct dvb_frontend *fe, u32 *frequency) { struct mxl5005s_state *state = fe->tuner_priv; - u8 buf[3] = { reg, val, MXL5005S_LATCH_BYTE }; - struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, - .buf = buf, .len = 3 }; - - if (latch == 0) - msg.len = 2; + dprintk(1, "%s()\n", __func__); - dprintk(2, "%s(reg = 0x%x val = 0x%x addr = 0x%x)\n", __func__, reg, val, msg.addr); + *frequency = state->RF_IN; - if (i2c_transfer(state->i2c, &msg, 1) != 1) { - printk(KERN_WARNING "mxl5005s I2C write failed\n"); - return -EREMOTEIO; - } return 0; } -int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, u8 len) +static int mxl5005s_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) { - int ret = 0, i; - - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 1); - - for (i = 0 ; i < len-1; i++) { - ret = mxl5005s_writereg(fe, addrtable[i], datatable[i], 0); - if (ret < 0) - break; - } - - ret = mxl5005s_writereg(fe, addrtable[i], datatable[i], 1); + struct mxl5005s_state *state = fe->tuner_priv; + dprintk(1, "%s()\n", __func__); - if (fe->ops.i2c_gate_ctrl) - fe->ops.i2c_gate_ctrl(fe, 0); + *bandwidth = state->Chan_Bandwidth; - return ret; + return 0; } - -int mxl5005s_init(struct dvb_frontend *fe) +static int mxl5005s_get_status(struct dvb_frontend *fe, u32 *status) { dprintk(1, "%s()\n", __func__); - return mxl5005s_reconfigure(fe, MXL_QAM, MXL5005S_BANDWIDTH_6MHZ); + + *status = 0; + // *status = TUNER_STATUS_LOCKED; + + return 0; } -int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth) +static int mxl5005s_init2(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; - u8 AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; u8 ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; int TableLen; - dprintk(1, "%s(type=%d, bw=%d)\n", __func__, mod_type, bandwidth); + dprintk(1, "%s()\n", __func__); - mxl5005s_reset(fe); + /* Initialize MxL5005S tuner according to MxL5005S tuner example code. */ /* Tuner initialization stage 0 */ MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET); AddrTable[0] = MASTER_CONTROL_ADDR; ByteTable[0] |= state->config->AgcMasterByte; - mxl5005s_writeregs(fe, AddrTable, ByteTable, 1); - - mxl5005s_AssignTunerMode(fe, mod_type, bandwidth); + mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1); /* Tuner initialization stage 1 */ MXL_GetInitRegister(fe, AddrTable, ByteTable, &TableLen); - mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen); - - return 0; -} - -int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth) -{ - struct mxl5005s_state *state = fe->tuner_priv; - struct mxl5005s_config *c = state->config; - - InitTunerControls(fe); - - /* Set MxL5005S parameters. */ - MXL5005_TunerConfig( - fe, - c->mod_mode, - c->if_mode, - bandwidth, - c->if_freq, - c->xtal_freq, - c->agc_mode, - c->top, - c->output_load, - c->clock_out, - c->div_out, - c->cap_select, - c->rssi_enable, - mod_type, - c->tracking_filter); - - return 0; -} - -static int mxl5005s_set_params(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params) -{ - struct mxl5005s_state *state = fe->tuner_priv; - u32 req_mode, req_bw = 0; - int ret; - - dprintk(1, "%s()\n", __func__); - - if (fe->ops.info.type == FE_ATSC) { - switch (params->u.vsb.modulation) { - case VSB_8: - req_mode = MXL_ATSC; break; - default: - case QAM_64: - case QAM_256: - case QAM_AUTO: - req_mode = MXL_QAM; break; - } - } - else req_mode = MXL_DVBT; - - /* Change tuner for new modulation type if reqd */ - if (req_mode != state->current_mode) { - switch (req_mode) { - case VSB_8: - case QAM_64: - case QAM_256: - case QAM_AUTO: - req_bw = MXL5005S_BANDWIDTH_6MHZ; - break; - default: - /* Assume DVB-T */ - switch (params->u.ofdm.bandwidth) { - case BANDWIDTH_6_MHZ: - req_bw = MXL5005S_BANDWIDTH_6MHZ; - break; - case BANDWIDTH_7_MHZ: - req_bw = MXL5005S_BANDWIDTH_7MHZ; - break; - case BANDWIDTH_AUTO: - case BANDWIDTH_8_MHZ: - req_bw = MXL5005S_BANDWIDTH_8MHZ; - break; - } - } - - state->current_mode = req_mode; - ret = mxl5005s_reconfigure(fe, req_mode, req_bw); - - } else - ret = 0; - - if (ret == 0) { - dprintk(1, "%s() freq=%d\n", __func__, params->frequency); - ret = mxl5005s_SetRfFreqHz(fe, params->frequency); - } - - return ret; -} - -static int mxl5005s_get_frequency(struct dvb_frontend *fe, u32 *frequency) -{ - struct mxl5005s_state *state = fe->tuner_priv; - dprintk(1, "%s()\n", __func__); - - *frequency = state->RF_IN; - - return 0; -} - -static int mxl5005s_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) -{ - struct mxl5005s_state *state = fe->tuner_priv; - dprintk(1, "%s()\n", __func__); - - *bandwidth = state->Chan_Bandwidth; + mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); return 0; } @@ -4631,6 +4698,7 @@ static const struct dvb_tuner_ops mxl5005s_tuner_ops = { .set_params = mxl5005s_set_params, .get_frequency = mxl5005s_get_frequency, .get_bandwidth = mxl5005s_get_bandwidth, + .get_status = mxl5005s_get_status }; struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, @@ -4647,7 +4715,6 @@ struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, state->frontend = fe; state->config = config; state->i2c = i2c; - state->current_mode = MXL_QAM; printk(KERN_INFO "MXL5005S: Attached at address 0x%02x\n", config->i2c_address); @@ -4659,5 +4726,8 @@ struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, EXPORT_SYMBOL(mxl5005s_attach); MODULE_DESCRIPTION("MaxLinear MXL5005S silicon tuner driver"); +MODULE_AUTHOR("Jan Hoogenraad"); +MODULE_AUTHOR("Barnaby Shearer"); +MODULE_AUTHOR("Andy Hasper"); MODULE_AUTHOR("Steven Toth"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h index 7658401..7d0727d 100644 --- a/drivers/media/common/tuners/mxl5005s.h +++ b/drivers/media/common/tuners/mxl5005s.h @@ -1,119 +1,66 @@ /* - MaxLinear MXL5005S VSB/QAM/DVBT tuner driver + * For the Realtek RTL chip RTL2831U + * Realtek Release Date: 2008-03-14, ver 080314 + * Realtek version RTL2831 Linux driver version 080314 + * ver 080314 + * + * for linux kernel version 2.6.21.4 - 2.6.22-14 + * support MXL5005s and MT2060 tuners (support tuner auto-detecting) + * support two IR types -- RC5 and NEC + * + * Known boards with Realtek RTL chip RTL2821U + * Freecom USB stick 14aa:0160 (version 4) + * Conceptronic CTVDIGRCU + * + * Copyright (c) 2008 Realtek + * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper + * This code is placed under the terms of the GNU General Public License + * + * Released by Realtek under GPLv2. + * Thanks to Realtek for a lot of support we received ! + * + * Revision: 080314 - original version + */ - Copyright (C) 2008 MaxLinear - Copyright (C) 2008 Steven Toth - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. +#ifndef __MXL5005S_H +#define __MXL5005S_H - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +#include -*/ +/* IF frequency */ +enum IF_FREQ_HZ +{ + IF_FREQ_4570000HZ = 4570000, ///< IF frequency = 4.57 MHz + IF_FREQ_4571429HZ = 4571429, ///< IF frequency = 4.571 MHz + IF_FREQ_5380000HZ = 5380000, ///< IF frequency = 5.38 MHz + IF_FREQ_36000000HZ = 36000000, ///< IF frequency = 36.000 MHz + IF_FREQ_36125000HZ = 36125000, ///< IF frequency = 36.125 MHz + IF_FREQ_36166667HZ = 36166667, ///< IF frequency = 36.167 MHz + IF_FREQ_44000000HZ = 44000000, ///< IF frequency = 44.000 MHz +}; -#ifndef __MXL5005S_H -#define __MXL5005S_H +/* Crystal frequency */ +enum CRYSTAL_FREQ_HZ +{ + CRYSTAL_FREQ_4000000HZ = 4000000, ///< Crystal frequency = 4.0 MHz + CRYSTAL_FREQ_16000000HZ = 16000000, ///< Crystal frequency = 16.0 MHz + CRYSTAL_FREQ_25000000HZ = 25000000, ///< Crystal frequency = 25.0 MHz + CRYSTAL_FREQ_28800000HZ = 28800000, ///< Crystal frequency = 28.8 MHz +}; struct mxl5005s_config { - /* 7 bit i2c address */ u8 i2c_address; -#define IF_FREQ_4570000HZ 4570000 -#define IF_FREQ_4571429HZ 4571429 -#define IF_FREQ_5380000HZ 5380000 -#define IF_FREQ_36000000HZ 36000000 -#define IF_FREQ_36125000HZ 36125000 -#define IF_FREQ_36166667HZ 36166667 -#define IF_FREQ_44000000HZ 44000000 - u32 if_freq; - -#define CRYSTAL_FREQ_4000000HZ 4000000 -#define CRYSTAL_FREQ_16000000HZ 16000000 -#define CRYSTAL_FREQ_25000000HZ 25000000 -#define CRYSTAL_FREQ_28800000HZ 28800000 - u32 xtal_freq; - -#define MXL_DUAL_AGC 0 -#define MXL_SINGLE_AGC 1 - u8 agc_mode; - -#define MXL_TF_DEFAULT 0 -#define MXL_TF_OFF 1 -#define MXL_TF_C 2 -#define MXL_TF_C_H 3 -#define MXL_TF_D 4 -#define MXL_TF_D_L 5 -#define MXL_TF_E 6 -#define MXL_TF_F 7 -#define MXL_TF_E_2 8 -#define MXL_TF_E_NA 9 -#define MXL_TF_G 10 - u8 tracking_filter; - -#define MXL_RSSI_DISABLE 0 -#define MXL_RSSI_ENABLE 1 - u8 rssi_enable; - -#define MXL_CAP_SEL_DISABLE 0 -#define MXL_CAP_SEL_ENABLE 1 - u8 cap_select; - -#define MXL_DIV_OUT_1 0 -#define MXL_DIV_OUT_4 1 - u8 div_out; - -#define MXL_CLOCK_OUT_DISABLE 0 -#define MXL_CLOCK_OUT_ENABLE 1 - u8 clock_out; - -#define MXL5005S_IF_OUTPUT_LOAD_200_OHM 200 -#define MXL5005S_IF_OUTPUT_LOAD_300_OHM 300 - u32 output_load; - -#define MXL5005S_TOP_5P5 55 -#define MXL5005S_TOP_7P2 72 -#define MXL5005S_TOP_9P2 92 -#define MXL5005S_TOP_11P0 110 -#define MXL5005S_TOP_12P9 129 -#define MXL5005S_TOP_14P7 147 -#define MXL5005S_TOP_16P8 168 -#define MXL5005S_TOP_19P4 194 -#define MXL5005S_TOP_21P2 212 -#define MXL5005S_TOP_23P2 232 -#define MXL5005S_TOP_25P2 252 -#define MXL5005S_TOP_27P1 271 -#define MXL5005S_TOP_29P2 292 -#define MXL5005S_TOP_31P7 317 -#define MXL5005S_TOP_34P9 349 - u32 top; - -#define MXL_ANALOG_MODE 0 -#define MXL_DIGITAL_MODE 1 - u8 mod_mode; - -#define MXL_ZERO_IF 0 -#define MXL_LOW_IF 1 - u8 if_mode; - /* Stuff I don't know what to do with */ u8 AgcMasterByte; }; -#if defined(CONFIG_DVB_TUNER_MXL5005S) || \ - (defined(CONFIG_DVB_TUNER_MXL5005S_MODULE) && defined(MODULE)) +#if defined(CONFIG_MEDIA_TUNER_MXL5005S) || (defined(CONFIG_MEDIA_TUNER_MXL5005S_MODULE) && defined(MODULE)) extern struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, - struct mxl5005s_config *config) + struct mxl5005s_config *config); #else static inline struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, -- cgit v1.1 From 48937295a63b4e81db907605afcbd81e0464b00f Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 1 May 2008 07:15:38 -0300 Subject: V4L/DVB(7871): mxl5005s: Re-org code and update copyrights Re-org code and update copyrights Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 608 +++++++++++++++------------------ drivers/media/common/tuners/mxl5005s.h | 143 +++++--- 2 files changed, 371 insertions(+), 380 deletions(-) diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index 64aa864..45ac6a9 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -1,27 +1,62 @@ /* - * For the Realtek RTL chip RTL2831U - * Realtek Release Date: 2008-03-14, ver 080314 - * Realtek version RTL2831 Linux driver version 080314 - * ver 080314 - * - * for linux kernel version 2.6.21.4 - 2.6.22-14 - * support MXL5005s and MT2060 tuners (support tuner auto-detecting) - * support two IR types -- RC5 and NEC - * - * Known boards with Realtek RTL chip RTL2821U - * Freecom USB stick 14aa:0160 (version 4) - * Conceptronic CTVDIGRCU - * - * Copyright (c) 2008 Realtek - * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper - * This code is placed under the terms of the GNU General Public License - * - * Released by Realtek under GPLv2. - * Thanks to Realtek for a lot of support we received ! - * - * Revision: 080314 - original version - */ + MaxLinear MXL5005S VSB/QAM/DVBT tuner driver + + Copyright (C) 2008 MaxLinear + Copyright (C) 2006 Steven Toth + Functions: + mxl5005s_reset() + mxl5005s_writereg() + mxl5005s_writeregs() + mxl5005s_init() + mxl5005s_reconfigure() + mxl5005s_AssignTunerMode() + mxl5005s_set_params() + mxl5005s_get_frequency() + mxl5005s_get_bandwidth() + mxl5005s_release() + mxl5005s_attach() + + Copyright (c) 2008 Realtek + Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper + Functions: + mxl5005s_SetRfFreqHz() + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/* + History of this driver (Steven Toth): + I was given a public release of a linux driver that included + support for the MaxLinear MXL5005S silicon tuner. Analysis of + the tuner driver showed clearly three things. + 1. The tuner driver didn't support the LinuxTV tuner API + so the code Realtek added had to be removed. + + 2. A significant amount of the driver is reference driver code + from MaxLinear, I felt it was important to identify and + preserve this. + + 3. New code has to be added to interface correctly with the + LinuxTV API, as a regular kernel module. + + Other than the reference driver enum's, I've clearly marked + sections of the code and retained the copyright of the + respective owners. +*/ #include #include #include @@ -31,10 +66,10 @@ #include "dvb_frontend.h" #include "mxl5005s.h" -static int debug; +static int debug = 2; #define dprintk(level, arg...) do { \ - if (debug >= level) \ + if (level <= debug) \ printk(arg); \ } while (0) @@ -50,13 +85,6 @@ static int debug; #define MXLCTRL_NUM 189 #define MASTER_CONTROL_ADDR 9 -/* Enumeration of AGC Mode */ -typedef enum -{ - MXL_DUAL_AGC = 0, - MXL_SINGLE_AGC -} AGC_Mode; - /* Enumeration of Master Control Register State */ typedef enum { @@ -66,51 +94,6 @@ typedef enum MC_SEQ_OFF } Master_Control_State; -/* Enumeration of MXL5005 Tuner Mode */ -typedef enum -{ - MXL_ANALOG_MODE = 0, - MXL_DIGITAL_MODE -} Tuner_Mode; - -/* Enumeration of MXL5005 Tuner IF Mode */ -typedef enum -{ - MXL_ZERO_IF = 0, - MXL_LOW_IF -} Tuner_IF_Mode; - -/* Enumeration of MXL5005 Tuner Clock Out Mode */ -typedef enum -{ - MXL_CLOCK_OUT_DISABLE = 0, - MXL_CLOCK_OUT_ENABLE -} Tuner_Clock_Out; - -/* Enumeration of MXL5005 Tuner Div Out Mode */ -typedef enum -{ - MXL_DIV_OUT_1 = 0, - MXL_DIV_OUT_4 - -} Tuner_Div_Out; - -/* Enumeration of MXL5005 Tuner Pull-up Cap Select Mode */ -typedef enum -{ - MXL_CAP_SEL_DISABLE = 0, - MXL_CAP_SEL_ENABLE - -} Tuner_Cap_Select; - -/* Enumeration of MXL5005 Tuner RSSI Mode */ -typedef enum -{ - MXL_RSSI_DISABLE = 0, - MXL_RSSI_ENABLE - -} Tuner_RSSI; - /* Enumeration of MXL5005 Tuner Modulation Type */ typedef enum { @@ -122,22 +105,6 @@ typedef enum MXL_ANALOG_OTA } Tuner_Modu_Type; -/* Enumeration of MXL5005 Tuner Tracking Filter Type */ -typedef enum -{ - MXL_TF_DEFAULT = 0, - MXL_TF_OFF, - MXL_TF_C, - MXL_TF_C_H, - MXL_TF_D, - MXL_TF_D_L, - MXL_TF_E, - MXL_TF_F, - MXL_TF_E_2, - MXL_TF_E_NA, - MXL_TF_G -} Tuner_TF_Type; - /* MXL5005 Tuner Register Struct */ typedef struct _TunerReg_struct { @@ -268,33 +235,6 @@ enum }; #define MXL5005S_BANDWIDTH_MODE_NUM 3 -/* Top modes */ -enum -{ - MXL5005S_TOP_5P5 = 55, - MXL5005S_TOP_7P2 = 72, - MXL5005S_TOP_9P2 = 92, - MXL5005S_TOP_11P0 = 110, - MXL5005S_TOP_12P9 = 129, - MXL5005S_TOP_14P7 = 147, - MXL5005S_TOP_16P8 = 168, - MXL5005S_TOP_19P4 = 194, - MXL5005S_TOP_21P2 = 212, - MXL5005S_TOP_23P2 = 232, - MXL5005S_TOP_25P2 = 252, - MXL5005S_TOP_27P1 = 271, - MXL5005S_TOP_29P2 = 292, - MXL5005S_TOP_31P7 = 317, - MXL5005S_TOP_34P9 = 349, -}; - -/* IF output load */ -enum -{ - MXL5005S_IF_OUTPUT_LOAD_200_OHM = 200, - MXL5005S_IF_OUTPUT_LOAD_300_OHM = 300, -}; - /* MXL5005 Tuner Control Struct */ typedef struct _TunerControl_struct { u16 Ctrl_Num; /* Control Number */ @@ -349,13 +289,15 @@ struct mxl5005s_state TunerRegs[TUNER_REGS_NUM]; /* Tuner Register Array Pointer */ /* Linux driver framework specific */ - const struct mxl5005s_config *config; - + struct mxl5005s_config *config; struct dvb_frontend *frontend; struct i2c_adapter *i2c; + + /* Cache values */ + u32 current_mode; + }; -// funcs u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value); u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value); u16 MXL_GetMasterControl(u8 *MasterReg, int state); @@ -372,14 +314,26 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq); void MXL_SynthIFLO_Calc(struct dvb_frontend *fe); void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe); u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count); -int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen); +int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, u8 len); u16 MXL_IFSynthInit(struct dvb_frontend *fe); -static int mxl5005s_init2(struct dvb_frontend *fe); +int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth); +int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth); + +/* ---------------------------------------------------------------- + * Begin: Custom code salvaged from the Realtek driver. + * Copyright (c) 2008 Realtek + * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper + * This code is placed under the terms of the GNU General Public License + * + * Released by Realtek under GPLv2. + * Thanks to Realtek for a lot of support we received ! + * + * Revision: 080314 - original version + */ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) { struct mxl5005s_state *state = fe->tuner_priv; - u8 AgcMasterByte = state->config->AgcMasterByte; unsigned char AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; unsigned char ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; int TableLen; @@ -396,7 +350,7 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) AddrTable[0] = MASTER_CONTROL_ADDR; ByteTable[0] |= state->config->AgcMasterByte; - mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1); + mxl5005s_writeregs(fe, AddrTable, ByteTable, 1); // Tuner RF frequency setting stage 1 MXL_TuneRF(fe, RfFreqHz); @@ -410,13 +364,13 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ; AddrTable[TableLen] = MASTER_CONTROL_ADDR ; - ByteTable[TableLen] = MasterControlByte | AgcMasterByte; + ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte; TableLen += 1; - mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); + mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen); // Wait 30 ms. - msleep(30); + msleep(150); // Tuner RF frequency setting stage 2 MXL_ControlWrite(fe, SEQ_FSM_PULSE, 1) ; @@ -425,101 +379,21 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ; AddrTable[TableLen] = MASTER_CONTROL_ADDR ; - ByteTable[TableLen] = MasterControlByte | AgcMasterByte ; + ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte ; TableLen += 1; - mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); + mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen); - return 0; -} + msleep(100); -/* Write a single byte to a single reg */ -static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val) -{ - struct mxl5005s_state *state = fe->tuner_priv; - u8 buf[2] = { reg, val }; - struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, - .buf = buf, .len = 2 }; - - if (i2c_transfer(state->i2c, &msg, 1) != 1) { - printk(KERN_WARNING "mxl5005s I2C write failed\n"); - return -EREMOTEIO; - } return 0; } +/* End: Custom code taken from the Realtek driver */ -/* Write a word to a single reg */ -static int mxl5005s_writereg16(struct dvb_frontend *fe, u8 reg, u16 val) -{ - struct mxl5005s_state *state = fe->tuner_priv; - u8 buf[3] = { reg, val >> 8 , val & 0xff }; - struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, - .buf = buf, .len = 3 }; - - if (i2c_transfer(state->i2c, &msg, 1) != 1) { - printk(KERN_WARNING "mxl5005s I2C write16 failed\n"); - return -EREMOTEIO; - } - return 0; -} - -int mxl5005s_SetRegsWithTable(struct dvb_frontend *fe, u8 *pAddrTable, u8 *pByteTable, int TableLen) -{ - int i, ret; - u8 end_two_bytes_buf[]={ 0 , 0 }; - - for( i = 0 ; i < TableLen - 1 ; i++) - { - ret = mxl5005s_writereg(fe, pAddrTable[i], pByteTable[i]); - if (!ret) - return ret; - } - - end_two_bytes_buf[0] = pByteTable[i]; - end_two_bytes_buf[1] = MXL5005S_LATCH_BYTE; - - ret = mxl5005s_writereg16(fe, pAddrTable[i], (end_two_bytes_buf[0] << 8) | end_two_bytes_buf[1]); - - return ret; -} - -int mxl5005s_SetRegMaskBits(struct dvb_frontend *fe, - unsigned char RegAddr, - unsigned char Msb, - unsigned char Lsb, - const unsigned char WritingValue - ) -{ - int i; - - unsigned char Mask; - unsigned char Shift; - unsigned char RegByte; - - /* Generate mask and shift according to MSB and LSB. */ - Mask = 0; - for(i = Lsb; i < (unsigned char)(Msb + 1); i++) - Mask |= 0x1 << i; - - Shift = Lsb; - - /* Get tuner register byte according to register adddress. */ - MXL_RegRead(fe, RegAddr, &RegByte); - - /* Reserve register byte unmask bit with mask and inlay writing value into it. */ - RegByte &= ~Mask; - RegByte |= (WritingValue << Shift) & Mask; - - /* Update tuner register byte table. */ - MXL_RegWrite(fe, RegAddr, RegByte); - - /* Write tuner register byte with writing byte. */ - return mxl5005s_SetRegsWithTable(fe, &RegAddr, &RegByte, 1); -} - -// The following context is source code provided by MaxLinear. -// MaxLinear source code - MXL5005_Initialize.cpp -// DONE +/* ---------------------------------------------------------------- + * Begin: Reference driver code found in the Realtek driver. + * Copyright (c) 2008 MaxLinear + */ u16 MXL5005_RegisterInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -841,7 +715,6 @@ u16 MXL5005_RegisterInit(struct dvb_frontend *fe) return 0 ; } -// DONE u16 MXL5005_ControlInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -1785,7 +1658,6 @@ u16 MXL5005_ControlInit(struct dvb_frontend *fe) // MaxLinear source code - MXL5005_c.cpp // MXL5005.cpp : Defines the initialization routines for the DLL. // 2.6.12 -// DONE void InitTunerControls(struct dvb_frontend *fe) { MXL5005_RegisterInit(fe); @@ -1828,7 +1700,6 @@ void InitTunerControls(struct dvb_frontend *fe) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL5005_TunerConfig(struct dvb_frontend *fe, u8 Mode, /* 0: Analog Mode ; 1: Digital Mode */ u8 IF_mode, /* for Analog Mode, 0: zero IF; 1: low IF */ @@ -1898,7 +1769,6 @@ u16 MXL5005_TunerConfig(struct dvb_frontend *fe, // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -// DONE void MXL_SynthIFLO_Calc(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -1937,7 +1807,6 @@ void MXL_SynthIFLO_Calc(struct dvb_frontend *fe) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -// DONE void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -1976,7 +1845,6 @@ void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) { u16 status = 0; @@ -2014,7 +1882,6 @@ u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) // > 0 : Failed // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_BlockInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -2042,6 +1909,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 2); break; case 6000000: + printk("%s() doing 6MHz digital\n", __func__); status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 3); break; } @@ -2072,7 +1940,6 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) else /* Single AGC Mode Dig Ana */ status += MXL_ControlWrite(fe, AGC_RF, state->Mode ? 15 : 12); - if (state->TOP == 55) /* TOP == 5.5 */ status += MXL_ControlWrite(fe, AGC_IF, 0x0); @@ -2302,6 +2169,8 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) status += MXL_ControlWrite(fe, BB_IQSWAP, 0); else /* High IF */ status += MXL_ControlWrite(fe, BB_IQSWAP, 1); + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 2); + } if (state->Mod_Type == MXL_ANALOG_CABLE) { /* Analog Cable Mode */ @@ -2338,7 +2207,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) } /* RSSI disable */ - if(state->EN_RSSI==0) { + if(state->EN_RSSI == 0) { status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1); status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1); status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0); @@ -2547,6 +2416,7 @@ u16 MXL_IFSynthInit(struct dvb_frontend *fe) Fref = 324000000UL ; } if (state->IF_LO == 5380000UL) { + printk("%s() doing 5.38\n", __func__); status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; Fref = 322800000UL ; @@ -3229,6 +3099,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) if (state->TF_Type == MXL_TF_C_H) // Tracking Filter type C-H for Hauppauge only { + printk("%s() CH filter\n", __func__); status += MXL_ControlWrite(fe, DAC_DIN_A, 0) ; if (state->RF_IN >= 43000000 && state->RF_IN < 150000000) @@ -3767,7 +3638,6 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) return status ; } -// DONE u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val) { u16 status = 0; @@ -3834,7 +3704,6 @@ u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val) // >0 : Value exceed maximum allowed for control number // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value) { u16 status = 0; @@ -3875,7 +3744,6 @@ u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value) // 2 : Control name not found // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u16 controlGroup) { struct mxl5005s_state *state = fe->tuner_priv; @@ -3982,7 +3850,6 @@ u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u // -1 : Invalid Register Address // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4022,7 +3889,6 @@ u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) // -1 : Invalid Register Address // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4059,7 +3925,6 @@ u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) // -1 : Invalid control name // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4131,7 +3996,6 @@ u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value) // -1 : Invalid control name // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int * count) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4237,7 +4101,6 @@ u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int // NONE // // // /////////////////////////////////////////////////////////////////////////////// -// DONE void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4285,7 +4148,6 @@ void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal) // Computed value // // // /////////////////////////////////////////////////////////////////////////////// -// DONE u32 MXL_Ceiling(u32 value, u32 resolution) { return (value/resolution + (value % resolution > 0 ? 1 : 0)); @@ -4294,7 +4156,6 @@ u32 MXL_Ceiling(u32 value, u32 resolution) // // Retrieve the Initialzation Registers // -// DONE u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { u16 status = 0; @@ -4317,7 +4178,6 @@ u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *c return status; } -// DONE u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { u16 status = 0; @@ -4345,7 +4205,6 @@ u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *cou return status; } -// DONE u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { u16 status = 0; @@ -4363,7 +4222,6 @@ u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, i return status; } -// DONE u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) { u16 status = 0; @@ -4381,7 +4239,6 @@ u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, in return status; } -// DONE u16 MXL_GetMasterControl(u8 *MasterReg, int state) { if (state == 1) /* Load_Start */ @@ -4526,7 +4383,6 @@ u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range) return status; } -// DONE u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4537,141 +4393,224 @@ u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis) return status; } - #endif +/* End: Reference driver code found in the Realtek driver that + * is copyright MaxLinear */ -/* Linux driver related functions */ - - -int mxl5005s_init(struct dvb_frontend *fe) +/* ---------------------------------------------------------------- + * Begin: Everything after here is new code to adapt the + * proprietary Realtek driver into a Linux API tuner. + * Copyright (C) 2008 Steven Toth + */ +static int mxl5005s_reset(struct dvb_frontend *fe) { - int MxlModMode; - int MxlIfMode; - unsigned long MxlBandwitdh; - unsigned long MxlIfFreqHz; - unsigned long MxlCrystalFreqHz; - int MxlAgcMode; - unsigned short MxlTop; - unsigned short MxlIfOutputLoad; - int MxlClockOut; - int MxlDivOut; - int MxlCapSel; - int MxlRssiOnOff; - unsigned char MxlStandard; - unsigned char MxlTfType; + struct mxl5005s_state *state = fe->tuner_priv; + int ret = 0; - /* Set MxL5005S parameters. */ - MxlModMode = MXL_DIGITAL_MODE; - MxlIfMode = MXL_ZERO_IF; -// steve - //MxlBandwitdh = MXL5005S_BANDWIDTH_8MHZ; - //MxlIfFreqHz = IF_FREQ_4570000HZ; - MxlBandwitdh = MXL5005S_BANDWIDTH_6MHZ; // config - MxlIfFreqHz = IF_FREQ_5380000HZ; // config - MxlCrystalFreqHz = CRYSTAL_FREQ_16000000HZ; // config - MxlAgcMode = MXL_SINGLE_AGC; - MxlTop = MXL5005S_TOP_25P2; - MxlIfOutputLoad = MXL5005S_IF_OUTPUT_LOAD_200_OHM; - MxlClockOut = MXL_CLOCK_OUT_DISABLE; - MxlDivOut = MXL_DIV_OUT_4; - MxlCapSel = MXL_CAP_SEL_ENABLE; - MxlRssiOnOff = MXL_RSSI_ENABLE; // config - MxlTfType = MXL_TF_C_H; // config - - MxlStandard = MXL_ATSC; // config - - // TODO: this is bad, it trashes other configs - // Set MxL5005S extra module. - //pExtra->AgcMasterByte = (MxlAgcMode == MXL_DUAL_AGC) ? 0x4 : 0x0; + u8 buf[2] = { 0xff, 0x00 }; + struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, + .buf = buf, .len = 2 }; - MXL5005_TunerConfig( - fe, - (unsigned char)MxlModMode, - (unsigned char)MxlIfMode, - MxlBandwitdh, - MxlIfFreqHz, - MxlCrystalFreqHz, - (unsigned char)MxlAgcMode, - MxlTop, - MxlIfOutputLoad, - (unsigned char)MxlClockOut, - (unsigned char)MxlDivOut, - (unsigned char)MxlCapSel, - (unsigned char)MxlRssiOnOff, - MxlStandard, MxlTfType); - - return mxl5005s_init2(fe); -} + dprintk(2, "%s()\n", __func__); -static int mxl5005s_set_params(struct dvb_frontend *fe, - struct dvb_frontend_parameters *params) -{ - u32 freq; - u32 bw; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); - if (fe->ops.info.type == FE_OFDM) - bw = params->u.ofdm.bandwidth; - else - bw = MXL5005S_BANDWIDTH_6MHZ; + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + printk(KERN_WARNING "mxl5005s I2C reset failed\n"); + ret = -EREMOTEIO; + } - freq = params->frequency; /* Hz */ - dprintk(1, "%s() freq=%d bw=%d\n", __func__, freq, bw); + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); - return mxl5005s_SetRfFreqHz(fe, freq); + return ret; } -static int mxl5005s_get_frequency(struct dvb_frontend *fe, u32 *frequency) +/* Write a single byte to a single reg, latch the value if required by + * following the transaction with the latch byte. + */ +static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val, int latch) { struct mxl5005s_state *state = fe->tuner_priv; - dprintk(1, "%s()\n", __func__); + u8 buf[3] = { reg, val, MXL5005S_LATCH_BYTE }; + struct i2c_msg msg = { .addr = state->config->i2c_address, .flags = 0, + .buf = buf, .len = 3 }; - *frequency = state->RF_IN; + if (latch == 0) + msg.len = 2; + dprintk(2, "%s(reg = 0x%x val = 0x%x addr = 0x%x)\n", __func__, reg, val, msg.addr); + + if (i2c_transfer(state->i2c, &msg, 1) != 1) { + printk(KERN_WARNING "mxl5005s I2C write failed\n"); + return -EREMOTEIO; + } return 0; } -static int mxl5005s_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, u8 len) { - struct mxl5005s_state *state = fe->tuner_priv; - dprintk(1, "%s()\n", __func__); + int ret = 0, i; - *bandwidth = state->Chan_Bandwidth; + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 1); - return 0; + for (i = 0 ; i < len-1; i++) { + ret = mxl5005s_writereg(fe, addrtable[i], datatable[i], 0); + if (ret < 0) + break; + } + + ret = mxl5005s_writereg(fe, addrtable[i], datatable[i], 1); + + if (fe->ops.i2c_gate_ctrl) + fe->ops.i2c_gate_ctrl(fe, 0); + + return ret; } -static int mxl5005s_get_status(struct dvb_frontend *fe, u32 *status) + +int mxl5005s_init(struct dvb_frontend *fe) { dprintk(1, "%s()\n", __func__); - - *status = 0; - // *status = TUNER_STATUS_LOCKED; - - return 0; + return mxl5005s_reconfigure(fe, MXL_QAM, MXL5005S_BANDWIDTH_6MHZ); } -static int mxl5005s_init2(struct dvb_frontend *fe) +int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth) { struct mxl5005s_state *state = fe->tuner_priv; + u8 AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; u8 ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; int TableLen; - dprintk(1, "%s()\n", __func__); + dprintk(1, "%s(type=%d, bw=%d)\n", __func__, mod_type, bandwidth); - /* Initialize MxL5005S tuner according to MxL5005S tuner example code. */ + mxl5005s_reset(fe); /* Tuner initialization stage 0 */ MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET); AddrTable[0] = MASTER_CONTROL_ADDR; ByteTable[0] |= state->config->AgcMasterByte; - mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, 1); + mxl5005s_writeregs(fe, AddrTable, ByteTable, 1); + + mxl5005s_AssignTunerMode(fe, mod_type, bandwidth); /* Tuner initialization stage 1 */ MXL_GetInitRegister(fe, AddrTable, ByteTable, &TableLen); - mxl5005s_SetRegsWithTable(fe, AddrTable, ByteTable, TableLen); + mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen); + + return 0; +} + +int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth) +{ + struct mxl5005s_state *state = fe->tuner_priv; + struct mxl5005s_config *c = state->config; + + InitTunerControls(fe); + + /* Set MxL5005S parameters. */ + MXL5005_TunerConfig( + fe, + c->mod_mode, + c->if_mode, + bandwidth, + c->if_freq, + c->xtal_freq, + c->agc_mode, + c->top, + c->output_load, + c->clock_out, + c->div_out, + c->cap_select, + c->rssi_enable, + mod_type, + c->tracking_filter); + + return 0; +} + +static int mxl5005s_set_params(struct dvb_frontend *fe, + struct dvb_frontend_parameters *params) +{ + struct mxl5005s_state *state = fe->tuner_priv; + u32 req_mode, req_bw = 0; + int ret; + + dprintk(1, "%s()\n", __func__); + + if (fe->ops.info.type == FE_ATSC) { + switch (params->u.vsb.modulation) { + case VSB_8: + req_mode = MXL_ATSC; break; + default: + case QAM_64: + case QAM_256: + case QAM_AUTO: + req_mode = MXL_QAM; break; + } + } + else req_mode = MXL_DVBT; + + /* Change tuner for new modulation type if reqd */ + if (req_mode != state->current_mode) { + switch (req_mode) { + case VSB_8: + case QAM_64: + case QAM_256: + case QAM_AUTO: + req_bw = MXL5005S_BANDWIDTH_6MHZ; + break; + default: + /* Assume DVB-T */ + switch (params->u.ofdm.bandwidth) { + case BANDWIDTH_6_MHZ: + req_bw = MXL5005S_BANDWIDTH_6MHZ; + break; + case BANDWIDTH_7_MHZ: + req_bw = MXL5005S_BANDWIDTH_7MHZ; + break; + case BANDWIDTH_AUTO: + case BANDWIDTH_8_MHZ: + req_bw = MXL5005S_BANDWIDTH_8MHZ; + break; + } + } + + state->current_mode = req_mode; + ret = mxl5005s_reconfigure(fe, req_mode, req_bw); + + } else + ret = 0; + + if (ret == 0) { + dprintk(1, "%s() freq=%d\n", __func__, params->frequency); + ret = mxl5005s_SetRfFreqHz(fe, params->frequency); + } + + return ret; +} + +static int mxl5005s_get_frequency(struct dvb_frontend *fe, u32 *frequency) +{ + struct mxl5005s_state *state = fe->tuner_priv; + dprintk(1, "%s()\n", __func__); + + *frequency = state->RF_IN; + + return 0; +} + +static int mxl5005s_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth) +{ + struct mxl5005s_state *state = fe->tuner_priv; + dprintk(1, "%s()\n", __func__); + + *bandwidth = state->Chan_Bandwidth; return 0; } @@ -4698,7 +4637,6 @@ static const struct dvb_tuner_ops mxl5005s_tuner_ops = { .set_params = mxl5005s_set_params, .get_frequency = mxl5005s_get_frequency, .get_bandwidth = mxl5005s_get_bandwidth, - .get_status = mxl5005s_get_status }; struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, @@ -4715,6 +4653,7 @@ struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, state->frontend = fe; state->config = config; state->i2c = i2c; + state->current_mode = MXL_QAM; printk(KERN_INFO "MXL5005S: Attached at address 0x%02x\n", config->i2c_address); @@ -4726,8 +4665,5 @@ struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, EXPORT_SYMBOL(mxl5005s_attach); MODULE_DESCRIPTION("MaxLinear MXL5005S silicon tuner driver"); -MODULE_AUTHOR("Jan Hoogenraad"); -MODULE_AUTHOR("Barnaby Shearer"); -MODULE_AUTHOR("Andy Hasper"); MODULE_AUTHOR("Steven Toth"); MODULE_LICENSE("GPL"); diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h index 7d0727d..687cf14 100644 --- a/drivers/media/common/tuners/mxl5005s.h +++ b/drivers/media/common/tuners/mxl5005s.h @@ -1,63 +1,118 @@ /* - * For the Realtek RTL chip RTL2831U - * Realtek Release Date: 2008-03-14, ver 080314 - * Realtek version RTL2831 Linux driver version 080314 - * ver 080314 - * - * for linux kernel version 2.6.21.4 - 2.6.22-14 - * support MXL5005s and MT2060 tuners (support tuner auto-detecting) - * support two IR types -- RC5 and NEC - * - * Known boards with Realtek RTL chip RTL2821U - * Freecom USB stick 14aa:0160 (version 4) - * Conceptronic CTVDIGRCU - * - * Copyright (c) 2008 Realtek - * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper - * This code is placed under the terms of the GNU General Public License - * - * Released by Realtek under GPLv2. - * Thanks to Realtek for a lot of support we received ! - * - * Revision: 080314 - original version - */ + MaxLinear MXL5005S VSB/QAM/DVBT tuner driver + Copyright (C) 2008 MaxLinear + Copyright (C) 2008 Steven Toth + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ #ifndef __MXL5005S_H #define __MXL5005S_H #include -/* IF frequency */ -enum IF_FREQ_HZ -{ - IF_FREQ_4570000HZ = 4570000, ///< IF frequency = 4.57 MHz - IF_FREQ_4571429HZ = 4571429, ///< IF frequency = 4.571 MHz - IF_FREQ_5380000HZ = 5380000, ///< IF frequency = 5.38 MHz - IF_FREQ_36000000HZ = 36000000, ///< IF frequency = 36.000 MHz - IF_FREQ_36125000HZ = 36125000, ///< IF frequency = 36.125 MHz - IF_FREQ_36166667HZ = 36166667, ///< IF frequency = 36.167 MHz - IF_FREQ_44000000HZ = 44000000, ///< IF frequency = 44.000 MHz -}; - -/* Crystal frequency */ -enum CRYSTAL_FREQ_HZ -{ - CRYSTAL_FREQ_4000000HZ = 4000000, ///< Crystal frequency = 4.0 MHz - CRYSTAL_FREQ_16000000HZ = 16000000, ///< Crystal frequency = 16.0 MHz - CRYSTAL_FREQ_25000000HZ = 25000000, ///< Crystal frequency = 25.0 MHz - CRYSTAL_FREQ_28800000HZ = 28800000, ///< Crystal frequency = 28.8 MHz -}; - struct mxl5005s_config { + /* 7 bit i2c address */ u8 i2c_address; +#define IF_FREQ_4570000HZ 4570000 +#define IF_FREQ_4571429HZ 4571429 +#define IF_FREQ_5380000HZ 5380000 +#define IF_FREQ_36000000HZ 36000000 +#define IF_FREQ_36125000HZ 36125000 +#define IF_FREQ_36166667HZ 36166667 +#define IF_FREQ_44000000HZ 44000000 + u32 if_freq; + +#define CRYSTAL_FREQ_4000000HZ 4000000 +#define CRYSTAL_FREQ_16000000HZ 16000000 +#define CRYSTAL_FREQ_25000000HZ 25000000 +#define CRYSTAL_FREQ_28800000HZ 28800000 + u32 xtal_freq; + +#define MXL_DUAL_AGC 0 +#define MXL_SINGLE_AGC 1 + u8 agc_mode; + +#define MXL_TF_DEFAULT 0 +#define MXL_TF_OFF 1 +#define MXL_TF_C 2 +#define MXL_TF_C_H 3 +#define MXL_TF_D 4 +#define MXL_TF_D_L 5 +#define MXL_TF_E 6 +#define MXL_TF_F 7 +#define MXL_TF_E_2 8 +#define MXL_TF_E_NA 9 +#define MXL_TF_G 10 + u8 tracking_filter; + +#define MXL_RSSI_DISABLE 0 +#define MXL_RSSI_ENABLE 1 + u8 rssi_enable; + +#define MXL_CAP_SEL_DISABLE 0 +#define MXL_CAP_SEL_ENABLE 1 + u8 cap_select; + +#define MXL_DIV_OUT_1 0 +#define MXL_DIV_OUT_4 1 + u8 div_out; + +#define MXL_CLOCK_OUT_DISABLE 0 +#define MXL_CLOCK_OUT_ENABLE 1 + u8 clock_out; + +#define MXL5005S_IF_OUTPUT_LOAD_200_OHM 200 +#define MXL5005S_IF_OUTPUT_LOAD_300_OHM 300 + u32 output_load; + +#define MXL5005S_TOP_5P5 55 +#define MXL5005S_TOP_7P2 72 +#define MXL5005S_TOP_9P2 92 +#define MXL5005S_TOP_11P0 110 +#define MXL5005S_TOP_12P9 129 +#define MXL5005S_TOP_14P7 147 +#define MXL5005S_TOP_16P8 168 +#define MXL5005S_TOP_19P4 194 +#define MXL5005S_TOP_21P2 212 +#define MXL5005S_TOP_23P2 232 +#define MXL5005S_TOP_25P2 252 +#define MXL5005S_TOP_27P1 271 +#define MXL5005S_TOP_29P2 292 +#define MXL5005S_TOP_31P7 317 +#define MXL5005S_TOP_34P9 349 + u32 top; + +#define MXL_ANALOG_MODE 0 +#define MXL_DIGITAL_MODE 1 + u8 mod_mode; + +#define MXL_ZERO_IF 0 +#define MXL_LOW_IF 1 + u8 if_mode; + /* Stuff I don't know what to do with */ u8 AgcMasterByte; }; -#if defined(CONFIG_MEDIA_TUNER_MXL5005S) || (defined(CONFIG_MEDIA_TUNER_MXL5005S_MODULE) && defined(MODULE)) +#if defined(CONFIG_MEDIA_TUNER_MXL5005S) || \ + (defined(CONFIG_MEDIA_TUNER_MXL5005S_MODULE) && defined(MODULE)) extern struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct mxl5005s_config *config); -- cgit v1.1 From d211017b954436bfc516e93d839e8746ec2bbbfe Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 1 May 2008 19:35:54 -0300 Subject: V4L/DVB(7872): mxl5005s: checkpatch.pl compliance 4 exceptions where the code would read very ugly otherwise. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 2496 +++++++++++++------------------- drivers/media/common/tuners/mxl5005s.h | 4 +- 2 files changed, 1029 insertions(+), 1471 deletions(-) diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index 45ac6a9..21dca5b 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -86,34 +86,30 @@ static int debug = 2; #define MASTER_CONTROL_ADDR 9 /* Enumeration of Master Control Register State */ -typedef enum -{ +enum master_control_state { MC_LOAD_START = 1, MC_POWER_DOWN, MC_SYNTH_RESET, MC_SEQ_OFF -} Master_Control_State; +}; /* Enumeration of MXL5005 Tuner Modulation Type */ -typedef enum -{ +enum { MXL_DEFAULT_MODULATION = 0, MXL_DVBT, MXL_ATSC, MXL_QAM, MXL_ANALOG_CABLE, MXL_ANALOG_OTA -} Tuner_Modu_Type; +} tuner_modu_type; /* MXL5005 Tuner Register Struct */ -typedef struct _TunerReg_struct -{ +struct TunerReg { u16 Reg_Num; /* Tuner Register Address */ - u16 Reg_Val; /* Current sofware programmed value waiting to be writen */ -} TunerReg_struct; + u16 Reg_Val; /* Current sw programmed value waiting to be writen */ +}; -typedef enum -{ +enum { /* Initialization Control Names */ DN_IQTN_AMP_CUT = 1, /* 1 */ BB_MODE, /* 2 */ @@ -219,16 +215,14 @@ typedef enum #define MXL5005S_BB_DLPF_BANDSEL_LSB 3 /* Standard modes */ -enum -{ +enum { MXL5005S_STANDARD_DVBT, MXL5005S_STANDARD_ATSC, }; #define MXL5005S_STANDARD_MODE_NUM 2 /* Bandwidth modes */ -enum -{ +enum { MXL5005S_BANDWIDTH_6MHZ = 6000000, MXL5005S_BANDWIDTH_7MHZ = 7000000, MXL5005S_BANDWIDTH_8MHZ = 8000000, @@ -236,17 +230,16 @@ enum #define MXL5005S_BANDWIDTH_MODE_NUM 3 /* MXL5005 Tuner Control Struct */ -typedef struct _TunerControl_struct { +struct TunerControl { u16 Ctrl_Num; /* Control Number */ u16 size; /* Number of bits to represent Value */ - u16 addr[25]; /* Array of Tuner Register Address for each bit position */ - u16 bit[25]; /* Array of bit position in Register Address for each bit position */ + u16 addr[25]; /* Array of Tuner Register Address for each bit pos */ + u16 bit[25]; /* Array of bit pos in Reg Addr for each bit pos */ u16 val[25]; /* Binary representation of Value */ -} TunerControl_struct; +}; /* MXL5005 Tuner Struct */ -struct mxl5005s_state -{ +struct mxl5005s_state { u8 Mode; /* 0: Analog Mode ; 1: Digital Mode */ u8 IF_Mode; /* for Analog Mode, 0: zero IF; 1: low IF */ u32 Chan_Bandwidth; /* filter channel bandwidth (6, 7, 8) */ @@ -256,14 +249,18 @@ struct mxl5005s_state u32 Fxtal; /* XTAL Frequency */ u8 AGC_Mode; /* AGC Mode 0: Dual AGC; 1: Single AGC */ u16 TOP; /* Value: take over point */ - u8 CLOCK_OUT; /* 0: turn off clock out; 1: turn on clock out */ + u8 CLOCK_OUT; /* 0: turn off clk out; 1: turn on clock out */ u8 DIV_OUT; /* 4MHz or 16MHz */ u8 CAPSELECT; /* 0: disable On-Chip pulling cap; 1: enable */ u8 EN_RSSI; /* 0: disable RSSI; 1: enable RSSI */ - u8 Mod_Type; /* Modulation Type; */ - /* 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable */ - u8 TF_Type; /* Tracking Filter Type */ - /* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */ + + /* Modulation Type; */ + /* 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable */ + u8 Mod_Type; + + /* Tracking Filter Type */ + /* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */ + u8 TF_Type; /* Calculated Settings */ u32 RF_LO; /* Synth RF LO Frequency */ @@ -271,22 +268,22 @@ struct mxl5005s_state u32 TG_LO; /* Synth TG_LO Frequency */ /* Pointers to ControlName Arrays */ - u16 Init_Ctrl_Num; /* Number of INIT Control Names */ - TunerControl_struct - Init_Ctrl[INITCTRL_NUM]; /* INIT Control Names Array Pointer */ + u16 Init_Ctrl_Num; /* Number of INIT Control Names */ + struct TunerControl + Init_Ctrl[INITCTRL_NUM]; /* INIT Control Names Array Pointer */ - u16 CH_Ctrl_Num; /* Number of CH Control Names */ - TunerControl_struct - CH_Ctrl[CHCTRL_NUM]; /* CH Control Name Array Pointer */ + u16 CH_Ctrl_Num; /* Number of CH Control Names */ + struct TunerControl + CH_Ctrl[CHCTRL_NUM]; /* CH Control Name Array Pointer */ - u16 MXL_Ctrl_Num; /* Number of MXL Control Names */ - TunerControl_struct - MXL_Ctrl[MXLCTRL_NUM]; /* MXL Control Name Array Pointer */ + u16 MXL_Ctrl_Num; /* Number of MXL Control Names */ + struct TunerControl + MXL_Ctrl[MXLCTRL_NUM]; /* MXL Control Name Array Pointer */ /* Pointer to Tuner Register Array */ - u16 TunerRegs_Num; /* Number of Tuner Registers */ - TunerReg_struct - TunerRegs[TUNER_REGS_NUM]; /* Tuner Register Array Pointer */ + u16 TunerRegs_Num; /* Number of Tuner Registers */ + struct TunerReg + TunerRegs[TUNER_REGS_NUM]; /* Tuner Register Array Pointer */ /* Linux driver framework specific */ struct mxl5005s_config *config; @@ -302,21 +299,27 @@ u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value); u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value); u16 MXL_GetMasterControl(u8 *MasterReg, int state); void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal); -u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count); +u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum, + u8 *RegVal, int *count); u32 MXL_Ceiling(u32 value, u32 resolution); u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal); u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal); -u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u16 controlGroup); +u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, + u32 value, u16 controlGroup); u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val); -u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count); +u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum, + u8 *RegVal, int *count); u32 MXL_GetXtalInt(u32 Xtal_Freq); u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq); void MXL_SynthIFLO_Calc(struct dvb_frontend *fe); void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe); -u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count); -int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, u8 len); +u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, + u8 *RegVal, int *count); +int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, + u8 *datatable, u8 len); u16 MXL_IFSynthInit(struct dvb_frontend *fe); -int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth); +int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, + u32 bandwidth); int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth); /* ---------------------------------------------------------------- @@ -343,16 +346,16 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) dprintk(1, "%s() freq=%ld\n", __func__, RfFreqHz); - // Set MxL5005S tuner RF frequency according to MxL5005S tuner example code. + /* Set MxL5005S tuner RF frequency according to example code. */ - // Tuner RF frequency setting stage 0 - MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET) ; + /* Tuner RF frequency setting stage 0 */ + MXL_GetMasterControl(ByteTable, MC_SYNTH_RESET); AddrTable[0] = MASTER_CONTROL_ADDR; ByteTable[0] |= state->config->AgcMasterByte; mxl5005s_writeregs(fe, AddrTable, ByteTable, 1); - // Tuner RF frequency setting stage 1 + /* Tuner RF frequency setting stage 1 */ MXL_TuneRF(fe, RfFreqHz); MXL_ControlRead(fe, IF_DIVVAL, &IfDivval); @@ -360,26 +363,28 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) MXL_ControlWrite(fe, SEQ_FSM_PULSE, 0); MXL_ControlWrite(fe, SEQ_EXTPOWERUP, 1); MXL_ControlWrite(fe, IF_DIVVAL, 8); - MXL_GetCHRegister(fe, AddrTable, ByteTable, &TableLen) ; + MXL_GetCHRegister(fe, AddrTable, ByteTable, &TableLen); - MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ; + MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START); AddrTable[TableLen] = MASTER_CONTROL_ADDR ; - ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte; + ByteTable[TableLen] = MasterControlByte | + state->config->AgcMasterByte; TableLen += 1; mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen); - // Wait 30 ms. + /* Wait 30 ms. */ msleep(150); - // Tuner RF frequency setting stage 2 - MXL_ControlWrite(fe, SEQ_FSM_PULSE, 1) ; - MXL_ControlWrite(fe, IF_DIVVAL, IfDivval) ; - MXL_GetCHRegister_ZeroIF(fe, AddrTable, ByteTable, &TableLen) ; + /* Tuner RF frequency setting stage 2 */ + MXL_ControlWrite(fe, SEQ_FSM_PULSE, 1); + MXL_ControlWrite(fe, IF_DIVVAL, IfDivval); + MXL_GetCHRegister_ZeroIF(fe, AddrTable, ByteTable, &TableLen); - MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START) ; + MXL_GetMasterControl(&MasterControlByte, MC_LOAD_START); AddrTable[TableLen] = MASTER_CONTROL_ADDR ; - ByteTable[TableLen] = MasterControlByte | state->config->AgcMasterByte ; + ByteTable[TableLen] = MasterControlByte | + state->config->AgcMasterByte ; TableLen += 1; mxl5005s_writeregs(fe, AddrTable, ByteTable, TableLen); @@ -398,7 +403,6 @@ u16 MXL5005_RegisterInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; state->TunerRegs_Num = TUNER_REGS_NUM ; -// state->TunerRegs = (TunerReg_struct *) calloc( TUNER_REGS_NUM, sizeof(TunerReg_struct) ) ; state->TunerRegs[0].Reg_Num = 9 ; state->TunerRegs[0].Reg_Val = 0x40 ; @@ -1655,9 +1659,6 @@ u16 MXL5005_ControlInit(struct dvb_frontend *fe) return 0 ; } -// MaxLinear source code - MXL5005_c.cpp -// MXL5005.cpp : Defines the initialization routines for the DLL. -// 2.6.12 void InitTunerControls(struct dvb_frontend *fe) { MXL5005_RegisterInit(fe); @@ -1667,57 +1668,28 @@ void InitTunerControls(struct dvb_frontend *fe) #endif } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL_ConfigTuner // -// // -// Description: Configure MXL5005Tuner structure for desired // -// Channel Bandwidth/Channel Frequency // -// // -// // -// Functions used: // -// MXL_SynthIFLO_Calc // -// // -// Inputs: // -// Tuner_struct: structure defined at higher level // -// Mode: Tuner Mode (Analog/Digital) // -// IF_Mode: IF Mode ( Zero/Low ) // -// Bandwidth: Filter Channel Bandwidth (in Hz) // -// IF_out: Desired IF out Frequency (in Hz) // -// Fxtal: Crystal Frerquency (in Hz) // -// TOP: 0: Dual AGC; Value: take over point // -// IF_OUT_LOAD: IF out load resistor (200/300 Ohms) // -// CLOCK_OUT: 0: Turn off clock out; 1: turn on clock out // -// DIV_OUT: 0: Div-1; 1: Div-4 // -// CAPSELECT: 0: Disable On-chip pulling cap; 1: Enable // -// EN_RSSI: 0: Disable RSSI; 1: Enable RSSI // -// // -// Outputs: // -// Tuner // -// // -// Return: // -// 0 : Successful // -// > 0 : Failed // -// // -/////////////////////////////////////////////////////////////////////////////// u16 MXL5005_TunerConfig(struct dvb_frontend *fe, - u8 Mode, /* 0: Analog Mode ; 1: Digital Mode */ - u8 IF_mode, /* for Analog Mode, 0: zero IF; 1: low IF */ - u32 Bandwidth, /* filter channel bandwidth (6, 7, 8) */ - u32 IF_out, /* Desired IF Out Frequency */ - u32 Fxtal, /* XTAL Frequency */ - u8 AGC_Mode, /* AGC Mode - Dual AGC: 0, Single AGC: 1 */ - u16 TOP, /* 0: Dual AGC; Value: take over point */ - u16 IF_OUT_LOAD, /* IF Out Load Resistor (200 / 300 Ohms) */ - u8 CLOCK_OUT, /* 0: turn off clock out; 1: turn on clock out */ - u8 DIV_OUT, /* 0: Div-1; 1: Div-4 */ - u8 CAPSELECT, /* 0: disable On-Chip pulling cap; 1: enable */ - u8 EN_RSSI, /* 0: disable RSSI; 1: enable RSSI */ - u8 Mod_Type, /* Modulation Type; */ - /* 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable */ - u8 TF_Type /* Tracking Filter */ - /* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */ - ) + u8 Mode, /* 0: Analog Mode ; 1: Digital Mode */ + u8 IF_mode, /* for Analog Mode, 0: zero IF; 1: low IF */ + u32 Bandwidth, /* filter channel bandwidth (6, 7, 8) */ + u32 IF_out, /* Desired IF Out Frequency */ + u32 Fxtal, /* XTAL Frequency */ + u8 AGC_Mode, /* AGC Mode - Dual AGC: 0, Single AGC: 1 */ + u16 TOP, /* 0: Dual AGC; Value: take over point */ + u16 IF_OUT_LOAD, /* IF Out Load Resistor (200 / 300 Ohms) */ + u8 CLOCK_OUT, /* 0: turn off clk out; 1: turn on clock out */ + u8 DIV_OUT, /* 0: Div-1; 1: Div-4 */ + u8 CAPSELECT, /* 0: disable On-Chip pulling cap; 1: enable */ + u8 EN_RSSI, /* 0: disable RSSI; 1: enable RSSI */ + + /* Modulation Type; */ + /* 0 - Default; 1 - DVB-T; 2 - ATSC; 3 - QAM; 4 - Analog Cable */ + u8 Mod_Type, + + /* Tracking Filter */ + /* 0 - Default; 1 - Off; 2 - Type C; 3 - Type C-H */ + u8 TF_Type + ) { struct mxl5005s_state *state = fe->tuner_priv; u16 status = 0; @@ -1746,105 +1718,40 @@ u16 MXL5005_TunerConfig(struct dvb_frontend *fe, return status; } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL_SynthIFLO_Calc // -// // -// Description: Calculate Internal IF-LO Frequency // -// // -// Globals: // -// NONE // -// // -// Functions used: // -// NONE // -// // -// Inputs: // -// Tuner_struct: structure defined at higher level // -// // -// Outputs: // -// Tuner // -// // -// Return: // -// 0 : Successful // -// > 0 : Failed // -// // -/////////////////////////////////////////////////////////////////////////////// void MXL_SynthIFLO_Calc(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; if (state->Mode == 1) /* Digital Mode */ state->IF_LO = state->IF_OUT; - else /* Analog Mode */ - { - if(state->IF_Mode == 0) /* Analog Zero IF mode */ + else /* Analog Mode */ { + if (state->IF_Mode == 0) /* Analog Zero IF mode */ state->IF_LO = state->IF_OUT + 400000; else /* Analog Low IF mode */ state->IF_LO = state->IF_OUT + state->Chan_Bandwidth/2; } } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL_SynthRFTGLO_Calc // -// // -// Description: Calculate Internal RF-LO frequency and // -// internal Tone-Gen(TG)-LO frequency // -// // -// Globals: // -// NONE // -// // -// Functions used: // -// NONE // -// // -// Inputs: // -// Tuner_struct: structure defined at higher level // -// // -// Outputs: // -// Tuner // -// // -// Return: // -// 0 : Successful // -// > 0 : Failed // -// // -/////////////////////////////////////////////////////////////////////////////// void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; if (state->Mode == 1) /* Digital Mode */ { - //remove 20.48MHz setting for 2.6.10 + /* remove 20.48MHz setting for 2.6.10 */ state->RF_LO = state->RF_IN; - state->TG_LO = state->RF_IN - 750000; //change for 2.6.6 + /* change for 2.6.6 */ + state->TG_LO = state->RF_IN - 750000; } else /* Analog Mode */ { - if(state->IF_Mode == 0) /* Analog Zero IF mode */ { + if (state->IF_Mode == 0) /* Analog Zero IF mode */ { state->RF_LO = state->RF_IN - 400000; state->TG_LO = state->RF_IN - 1750000; } else /* Analog Low IF mode */ { state->RF_LO = state->RF_IN - state->Chan_Bandwidth/2; - state->TG_LO = state->RF_IN - state->Chan_Bandwidth + 500000; + state->TG_LO = state->RF_IN - + state->Chan_Bandwidth + 500000; } } } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL_OverwriteICDefault // -// // -// Description: Overwrite the Default Register Setting // -// // -// // -// Functions used: // -// // -// Inputs: // -// Tuner_struct: structure defined at higher level // -// Outputs: // -// Tuner // -// // -// Return: // -// 0 : Successful // -// > 0 : Failed // -// // -/////////////////////////////////////////////////////////////////////////////// u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) { u16 status = 0; @@ -1857,31 +1764,6 @@ u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) return status; } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL_BlockInit // -// // -// Description: Tuner Initialization as a function of 'User Settings' // -// * User settings in Tuner strcuture must be assigned // -// first // -// // -// Globals: // -// NONE // -// // -// Functions used: // -// Tuner_struct: structure defined at higher level // -// // -// Inputs: // -// Tuner : Tuner structure defined at higher level // -// // -// Outputs: // -// Tuner // -// // -// Return: // -// 0 : Successful // -// > 0 : Failed // -// // -/////////////////////////////////////////////////////////////////////////////// u16 MXL_BlockInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -1902,42 +1784,45 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) /* Initialize Low-Pass Filter */ if (state->Mode) { /* Digital Mode */ switch (state->Chan_Bandwidth) { - case 8000000: - status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 0); - break; - case 7000000: - status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 2); - break; - case 6000000: - printk("%s() doing 6MHz digital\n", __func__); - status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 3); - break; + case 8000000: + status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 0); + break; + case 7000000: + status += MXL_ControlWrite(fe, BB_DLPF_BANDSEL, 2); + break; + case 6000000: + status += MXL_ControlWrite(fe, + BB_DLPF_BANDSEL, 3); + break; } } else { /* Analog Mode */ switch (state->Chan_Bandwidth) { - case 8000000: /* Low Zero */ - status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT, (state->IF_Mode ? 0 : 3)); - break; - case 7000000: - status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT, (state->IF_Mode ? 1 : 4)); - break; - case 6000000: - status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT, (state->IF_Mode ? 2 : 5)); - break; + case 8000000: /* Low Zero */ + status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT, + (state->IF_Mode ? 0 : 3)); + break; + case 7000000: + status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT, + (state->IF_Mode ? 1 : 4)); + break; + case 6000000: + status += MXL_ControlWrite(fe, BB_ALPF_BANDSELECT, + (state->IF_Mode ? 2 : 5)); + break; } } /* Charge Pump Control Dig Ana */ - status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, state->Mode ? 5 : 8); - status += MXL_ControlWrite(fe, RFSYN_EN_CHP_HIGAIN, state->Mode ? 1 : 1); + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, state->Mode ? 5 : 8); + status += MXL_ControlWrite(fe, + RFSYN_EN_CHP_HIGAIN, state->Mode ? 1 : 1); status += MXL_ControlWrite(fe, EN_CHP_LIN_B, state->Mode ? 0 : 0); /* AGC TOP Control */ if (state->AGC_Mode == 0) /* Dual AGC */ { status += MXL_ControlWrite(fe, AGC_IF, 15); status += MXL_ControlWrite(fe, AGC_RF, 15); - } - else /* Single AGC Mode Dig Ana */ + } else /* Single AGC Mode Dig Ana */ status += MXL_ControlWrite(fe, AGC_RF, state->Mode ? 15 : 12); if (state->TOP == 55) /* TOP == 5.5 */ @@ -2008,7 +1893,8 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) status += MXL_ControlWrite(fe, EN_AUX_3P, 1); status += MXL_ControlWrite(fe, SEL_AAF_BAND, 0); } - if ((state->IF_OUT == 36125000UL) || (state->IF_OUT == 36150000UL)) { + if ((state->IF_OUT == 36125000UL) || + (state->IF_OUT == 36150000UL)) { status += MXL_ControlWrite(fe, EN_AAF, 1); status += MXL_ControlWrite(fe, EN_3P, 1); status += MXL_ControlWrite(fe, EN_AUX_3P, 1); @@ -2021,15 +1907,13 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) status += MXL_ControlWrite(fe, SEL_AAF_BAND, 1); } } else { /* Analog Mode */ - if (state->IF_OUT >= 4000000UL && state->IF_OUT <= 5000000UL) - { + if (state->IF_OUT >= 4000000UL && state->IF_OUT <= 5000000UL) { status += MXL_ControlWrite(fe, EN_AAF, 1); status += MXL_ControlWrite(fe, EN_3P, 1); status += MXL_ControlWrite(fe, EN_AUX_3P, 1); status += MXL_ControlWrite(fe, SEL_AAF_BAND, 0); } - if (state->IF_OUT > 5000000UL) - { + if (state->IF_OUT > 5000000UL) { status += MXL_ControlWrite(fe, EN_AAF, 0); status += MXL_ControlWrite(fe, EN_3P, 0); status += MXL_ControlWrite(fe, EN_AUX_3P, 0); @@ -2073,13 +1957,13 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) /* status += MXL_ControlRead(fe, IF_DIVVAL, &IF_DIVVAL_Val); */ /* Set TG_R_DIV */ - status += MXL_ControlWrite(fe, TG_R_DIV, MXL_Ceiling(state->Fxtal, 1000000)); + status += MXL_ControlWrite(fe, TG_R_DIV, + MXL_Ceiling(state->Fxtal, 1000000)); /* Apply Default value to BB_INITSTATE_DLPF_TUNE */ /* RSSI Control */ - if (state->EN_RSSI) - { + if (state->EN_RSSI) { status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1); status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1); status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1); @@ -2098,8 +1982,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) /* Modulation type bit settings * Override the control values preset */ - if (state->Mod_Type == MXL_DVBT) /* DVB-T Mode */ - { + if (state->Mod_Type == MXL_DVBT) /* DVB-T Mode */ { state->AGC_Mode = 1; /* Single AGC Mode */ /* Enable RSSI */ @@ -2122,8 +2005,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) status += MXL_ControlWrite(fe, BB_IQSWAP, 1); } - if (state->Mod_Type == MXL_ATSC) /* ATSC Mode */ - { + if (state->Mod_Type == MXL_ATSC) /* ATSC Mode */ { state->AGC_Mode = 1; /* Single AGC Mode */ /* Enable RSSI */ @@ -2141,14 +2023,15 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) status += MXL_ControlWrite(fe, RFA_FLR, 2); status += MXL_ControlWrite(fe, RFA_CEIL, 13); status += MXL_ControlWrite(fe, BB_INITSTATE_DLPF_TUNE, 1); - status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 5); /* Low Zero */ + /* Low Zero */ + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 5); + if (state->IF_OUT <= 6280000UL) /* Low IF */ status += MXL_ControlWrite(fe, BB_IQSWAP, 0); else /* High IF */ status += MXL_ControlWrite(fe, BB_IQSWAP, 1); } - if (state->Mod_Type == MXL_QAM) /* QAM Mode */ - { + if (state->Mod_Type == MXL_QAM) /* QAM Mode */ { state->Mode = MXL_DIGITAL_MODE; /* state->AGC_Mode = 1; */ /* Single AGC Mode */ @@ -2163,7 +2046,8 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5); status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3); status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 2); - status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3); /* change here for v2.6.5 */ + /* change here for v2.6.5 */ + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3); if (state->IF_OUT <= 6280000UL) /* Low IF */ status += MXL_ControlWrite(fe, BB_IQSWAP, 0); @@ -2183,7 +2067,8 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1); status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0); status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1); - status += MXL_ControlWrite(fe, AGC_IF, 1); /* change for 2.6.3 */ + /* change for 2.6.3 */ + status += MXL_ControlWrite(fe, AGC_IF, 1); status += MXL_ControlWrite(fe, AGC_RF, 15); status += MXL_ControlWrite(fe, BB_IQSWAP, 1); } @@ -2207,7 +2092,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) } /* RSSI disable */ - if(state->EN_RSSI == 0) { + if (state->EN_RSSI == 0) { status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1); status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1); status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0); @@ -2217,34 +2102,10 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) return status; } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL_IFSynthInit // -// // -// Description: Tuner IF Synthesizer related register initialization // -// // -// Globals: // -// NONE // -// // -// Functions used: // -// Tuner_struct: structure defined at higher level // -// // -// Inputs: // -// Tuner : Tuner structure defined at higher level // -// // -// Outputs: // -// Tuner // -// // -// Return: // -// 0 : Successful // -// > 0 : Failed // -// // -/////////////////////////////////////////////////////////////////////////////// u16 MXL_IFSynthInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; u16 status = 0 ; - // Declare Local Variables u32 Fref = 0 ; u32 Kdbl, intModVal ; u32 fracModVal ; @@ -2255,268 +2116,207 @@ u16 MXL_IFSynthInit(struct dvb_frontend *fe) if (state->Fxtal > 16000000UL && state->Fxtal <= 32000000UL) Kdbl = 1 ; - // - // IF Synthesizer Control - // - if (state->Mode == 0 && state->IF_Mode == 1) // Analog Low IF mode - { + /* IF Synthesizer Control */ + if (state->Mode == 0 && state->IF_Mode == 1) /* Analog Low IF mode */ { if (state->IF_LO == 41000000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C); Fref = 328000000UL ; } if (state->IF_LO == 47000000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 376000000UL ; } if (state->IF_LO == 54000000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C); Fref = 324000000UL ; } if (state->IF_LO == 60000000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 360000000UL ; } if (state->IF_LO == 39250000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C); Fref = 314000000UL ; } if (state->IF_LO == 39650000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C); Fref = 317200000UL ; } if (state->IF_LO == 40150000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C); Fref = 321200000UL ; } if (state->IF_LO == 40650000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C); Fref = 325200000UL ; } } - if (state->Mode || (state->Mode == 0 && state->IF_Mode == 0)) - { + if (state->Mode || (state->Mode == 0 && state->IF_Mode == 0)) { if (state->IF_LO == 57000000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 342000000UL ; } if (state->IF_LO == 44000000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 352000000UL ; } if (state->IF_LO == 43750000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 350000000UL ; } if (state->IF_LO == 36650000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 366500000UL ; } if (state->IF_LO == 36150000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 361500000UL ; } if (state->IF_LO == 36000000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 360000000UL ; } if (state->IF_LO == 35250000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 352500000UL ; } if (state->IF_LO == 34750000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 347500000UL ; } if (state->IF_LO == 6280000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 376800000UL ; } if (state->IF_LO == 5000000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 360000000UL ; } if (state->IF_LO == 4500000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 360000000UL ; } if (state->IF_LO == 4570000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 365600000UL ; } if (state->IF_LO == 4000000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x05) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x05); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 360000000UL ; } - if (state->IF_LO == 57400000UL) - { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + if (state->IF_LO == 57400000UL) { + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x10); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 344400000UL ; } - if (state->IF_LO == 44400000UL) - { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + if (state->IF_LO == 44400000UL) { + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 355200000UL ; } - if (state->IF_LO == 44150000UL) - { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + if (state->IF_LO == 44150000UL) { + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x08); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 353200000UL ; } - if (state->IF_LO == 37050000UL) - { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + if (state->IF_LO == 37050000UL) { + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 370500000UL ; } - if (state->IF_LO == 36550000UL) - { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + if (state->IF_LO == 36550000UL) { + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 365500000UL ; } if (state->IF_LO == 36125000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x04); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 361250000UL ; } if (state->IF_LO == 6000000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 360000000UL ; } - if (state->IF_LO == 5400000UL) - { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; + if (state->IF_LO == 5400000UL) { + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C); Fref = 324000000UL ; } if (state->IF_LO == 5380000UL) { - printk("%s() doing 5.38\n", __func__); - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x07); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x0C); Fref = 322800000UL ; } if (state->IF_LO == 5200000UL) { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 374400000UL ; } - if (state->IF_LO == 4900000UL) - { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + if (state->IF_LO == 4900000UL) { + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x09); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 352800000UL ; } - if (state->IF_LO == 4400000UL) - { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + if (state->IF_LO == 4400000UL) { + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x06); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 352000000UL ; } - if (state->IF_LO == 4063000UL) //add for 2.6.8 - { - status += MXL_ControlWrite(fe, IF_DIVVAL, 0x05) ; - status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08) ; + if (state->IF_LO == 4063000UL) /* add for 2.6.8 */ { + status += MXL_ControlWrite(fe, IF_DIVVAL, 0x05); + status += MXL_ControlWrite(fe, IF_VCO_BIAS, 0x08); Fref = 365670000UL ; } } - // CHCAL_INT_MOD_IF - // CHCAL_FRAC_MOD_IF - intModVal = Fref / (state->Fxtal * Kdbl/2) ; - status += MXL_ControlWrite(fe, CHCAL_INT_MOD_IF, intModVal ) ; + /* CHCAL_INT_MOD_IF */ + /* CHCAL_FRAC_MOD_IF */ + intModVal = Fref / (state->Fxtal * Kdbl/2); + status += MXL_ControlWrite(fe, CHCAL_INT_MOD_IF, intModVal); + + fracModVal = (2<<15)*(Fref/1000 - (state->Fxtal/1000 * Kdbl/2) * + intModVal); - fracModVal = (2<<15)*(Fref/1000 - (state->Fxtal/1000 * Kdbl/2) * intModVal); - fracModVal = fracModVal / ((state->Fxtal * Kdbl/2)/1000) ; - status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_IF, fracModVal) ; + fracModVal = fracModVal / ((state->Fxtal * Kdbl/2)/1000); + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_IF, fracModVal); return status ; } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL_GetXtalInt // -// // -// Description: return the Crystal Integration Value for // -// TG_VCO_BIAS calculation // -// // -// Globals: // -// NONE // -// // -// Functions used: // -// NONE // -// // -// Inputs: // -// Crystal Frequency Value in Hz // -// // -// Outputs: // -// Calculated Crystal Frequency Integration Value // -// // -// Return: // -// 0 : Successful // -// > 0 : Failed // -// // -/////////////////////////////////////////////////////////////////////////////// u32 MXL_GetXtalInt(u32 Xtal_Freq) { if ((Xtal_Freq % 1000000) == 0) - return (Xtal_Freq / 10000) ; + return (Xtal_Freq / 10000); else - return (((Xtal_Freq / 1000000) + 1)*100) ; + return (((Xtal_Freq / 1000000) + 1)*100); } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL5005_TuneRF // -// // -// Description: Set control names to tune to requested RF_IN frequency // -// // -// Globals: // -// None // -// // -// Functions used: // -// MXL_SynthRFTGLO_Calc // -// MXL5005_ControlWrite // -// MXL_GetXtalInt // -// // -// Inputs: // -// Tuner : Tuner structure defined at higher level // -// // -// Outputs: // -// Tuner // -// // -// Return: // -// 0 : Successful // -// 1 : Unsuccessful // -/////////////////////////////////////////////////////////////////////////////// u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) { struct mxl5005s_state *state = fe->tuner_priv; - // Declare Local Variables u16 status = 0; u32 divider_val, E3, E4, E5, E5A; u32 Fmax, Fmin, FmaxBin, FminBin; @@ -2527,8 +2327,6 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) u32 Fref_TG; u32 Fvco; -// u32 temp; - Xtal_Int = MXL_GetXtalInt(state->Fxtal); @@ -2541,21 +2339,19 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) if (state->Fxtal > 22000000 && state->Fxtal <= 32000000) Kdbl_RF = 1; - // - // Downconverter Controls - // - // Look-Up Table Implementation for: - // DN_POLY - // DN_RFGAIN - // DN_CAP_RFLPF - // DN_EN_VHFUHFBAR - // DN_GAIN_ADJUST - // Change the boundary reference from RF_IN to RF_LO - if (state->RF_LO < 40000000UL) { + /* Downconverter Controls + * Look-Up Table Implementation for: + * DN_POLY + * DN_RFGAIN + * DN_CAP_RFLPF + * DN_EN_VHFUHFBAR + * DN_GAIN_ADJUST + * Change the boundary reference from RF_IN to RF_LO + */ + if (state->RF_LO < 40000000UL) return -1; - } + if (state->RF_LO >= 40000000UL && state->RF_LO <= 75000000UL) { - // Look-Up Table implementation status += MXL_ControlWrite(fe, DN_POLY, 2); status += MXL_ControlWrite(fe, DN_RFGAIN, 3); status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 423); @@ -2563,7 +2359,6 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 1); } if (state->RF_LO > 75000000UL && state->RF_LO <= 100000000UL) { - // Look-Up Table implementation status += MXL_ControlWrite(fe, DN_POLY, 3); status += MXL_ControlWrite(fe, DN_RFGAIN, 3); status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 222); @@ -2571,7 +2366,6 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 1); } if (state->RF_LO > 100000000UL && state->RF_LO <= 150000000UL) { - // Look-Up Table implementation status += MXL_ControlWrite(fe, DN_POLY, 3); status += MXL_ControlWrite(fe, DN_RFGAIN, 3); status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 147); @@ -2579,7 +2373,6 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 2); } if (state->RF_LO > 150000000UL && state->RF_LO <= 200000000UL) { - // Look-Up Table implementation status += MXL_ControlWrite(fe, DN_POLY, 3); status += MXL_ControlWrite(fe, DN_RFGAIN, 3); status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 9); @@ -2587,34 +2380,31 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 2); } if (state->RF_LO > 200000000UL && state->RF_LO <= 300000000UL) { - // Look-Up Table implementation - status += MXL_ControlWrite(fe, DN_POLY, 3) ; - status += MXL_ControlWrite(fe, DN_RFGAIN, 3) ; - status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 0) ; - status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 1) ; - status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 3) ; + status += MXL_ControlWrite(fe, DN_POLY, 3); + status += MXL_ControlWrite(fe, DN_RFGAIN, 3); + status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 0); + status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 1); + status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 3); } if (state->RF_LO > 300000000UL && state->RF_LO <= 650000000UL) { - // Look-Up Table implementation - status += MXL_ControlWrite(fe, DN_POLY, 3) ; - status += MXL_ControlWrite(fe, DN_RFGAIN, 1) ; - status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 0) ; - status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 0) ; - status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 3) ; + status += MXL_ControlWrite(fe, DN_POLY, 3); + status += MXL_ControlWrite(fe, DN_RFGAIN, 1); + status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 0); + status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 0); + status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 3); } if (state->RF_LO > 650000000UL && state->RF_LO <= 900000000UL) { - // Look-Up Table implementation - status += MXL_ControlWrite(fe, DN_POLY, 3) ; - status += MXL_ControlWrite(fe, DN_RFGAIN, 2) ; - status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 0) ; - status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 0) ; - status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 3) ; + status += MXL_ControlWrite(fe, DN_POLY, 3); + status += MXL_ControlWrite(fe, DN_RFGAIN, 2); + status += MXL_ControlWrite(fe, DN_CAP_RFLPF, 0); + status += MXL_ControlWrite(fe, DN_EN_VHFUHFBAR, 0); + status += MXL_ControlWrite(fe, DN_GAIN_ADJUST, 3); } - if (state->RF_LO > 900000000UL) { + if (state->RF_LO > 900000000UL) return -1; - } - // DN_IQTNBUF_AMP - // DN_IQTNGNBFBIAS_BST + + /* DN_IQTNBUF_AMP */ + /* DN_IQTNGNBFBIAS_BST */ if (state->RF_LO >= 40000000UL && state->RF_LO <= 75000000UL) { status += MXL_ControlWrite(fe, DN_IQTNBUF_AMP, 1); status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 0); @@ -2680,18 +2470,19 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) status += MXL_ControlWrite(fe, DN_IQTNGNBFBIAS_BST, 1); } - // - // Set RF Synth and LO Path Control - // - // Look-Up table implementation for: - // RFSYN_EN_OUTMUX - // RFSYN_SEL_VCO_OUT - // RFSYN_SEL_VCO_HI - // RFSYN_SEL_DIVM - // RFSYN_RF_DIV_BIAS - // DN_SEL_FREQ - // - // Set divider_val, Fmax, Fmix to use in Equations + /* + * Set RF Synth and LO Path Control + * + * Look-Up table implementation for: + * RFSYN_EN_OUTMUX + * RFSYN_SEL_VCO_OUT + * RFSYN_SEL_VCO_HI + * RFSYN_SEL_DIVM + * RFSYN_RF_DIV_BIAS + * DN_SEL_FREQ + * + * Set divider_val, Fmax, Fmix to use in Equations + */ FminBin = 28000000UL ; FmaxBin = 42500000UL ; if (state->RF_LO >= 40000000UL && state->RF_LO <= FmaxBin) { @@ -2721,12 +2512,12 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 56000000UL ; FmaxBin = 85000000UL ; if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(fe, DN_SEL_FREQ, 1) ; + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 1); divider_val = 32 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -2734,12 +2525,12 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 85000000UL ; FmaxBin = 112000000UL ; if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(fe, DN_SEL_FREQ, 1) ; + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 1); divider_val = 32 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -2747,12 +2538,12 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 112000000UL ; FmaxBin = 170000000UL ; if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(fe, DN_SEL_FREQ, 2) ; + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 2); divider_val = 16 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -2760,12 +2551,12 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 170000000UL ; FmaxBin = 225000000UL ; if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(fe, DN_SEL_FREQ, 2) ; + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 2); divider_val = 16 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -2773,12 +2564,12 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 225000000UL ; FmaxBin = 300000000UL ; if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(fe, DN_SEL_FREQ, 4) ; + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 4); divider_val = 8 ; Fmax = 340000000UL ; Fmin = FminBin ; @@ -2786,12 +2577,12 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 300000000UL ; FmaxBin = 340000000UL ; if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 1) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 0) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0) ; + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0); divider_val = 8 ; Fmax = FmaxBin ; Fmin = 225000000UL ; @@ -2799,12 +2590,12 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 340000000UL ; FmaxBin = 450000000UL ; if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 1) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 0) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0) ; - status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 2) ; - status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0) ; + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 0); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 2); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0); divider_val = 8 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -2812,12 +2603,12 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 450000000UL ; FmaxBin = 680000000UL ; if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 1) ; - status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0) ; + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 1); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0); divider_val = 4 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -2825,67 +2616,66 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 680000000UL ; FmaxBin = 900000000UL ; if (state->RF_LO > FminBin && state->RF_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1) ; - status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 1) ; - status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1) ; - status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0) ; + status += MXL_ControlWrite(fe, RFSYN_EN_OUTMUX, 0); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); + status += MXL_ControlWrite(fe, RFSYN_SEL_DIVM, 1); + status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); + status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0); divider_val = 4 ; Fmax = FmaxBin ; Fmin = FminBin ; } - // CHCAL_INT_MOD_RF - // CHCAL_FRAC_MOD_RF - // RFSYN_LPF_R - // CHCAL_EN_INT_RF - - // Equation E3 - // RFSYN_VCO_BIAS + /* CHCAL_INT_MOD_RF + * CHCAL_FRAC_MOD_RF + * RFSYN_LPF_R + * CHCAL_EN_INT_RF + */ + /* Equation E3 RFSYN_VCO_BIAS */ E3 = (((Fmax-state->RF_LO)/1000)*32)/((Fmax-Fmin)/1000) + 8 ; - status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, E3) ; + status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, E3); - // Equation E4 - // CHCAL_INT_MOD_RF - E4 = (state->RF_LO*divider_val/1000)/(2*state->Fxtal*Kdbl_RF/1000) ; - MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, E4) ; + /* Equation E4 CHCAL_INT_MOD_RF */ + E4 = (state->RF_LO*divider_val/1000)/(2*state->Fxtal*Kdbl_RF/1000); + MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, E4); - // Equation E5 - // CHCAL_FRAC_MOD_RF - // CHCAL_EN_INT_RF - E5 = ((2<<17)*(state->RF_LO/10000*divider_val - (E4*(2*state->Fxtal*Kdbl_RF)/10000)))/(2*state->Fxtal*Kdbl_RF/10000) ; - status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, E5) ; + /* Equation E5 CHCAL_FRAC_MOD_RF CHCAL_EN_INT_RF */ + E5 = ((2<<17)*(state->RF_LO/10000*divider_val - + (E4*(2*state->Fxtal*Kdbl_RF)/10000))) / + (2*state->Fxtal*Kdbl_RF/10000); - // Equation E5A - // RFSYN_LPF_R + status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, E5); + + /* Equation E5A RFSYN_LPF_R */ E5A = (((Fmax - state->RF_LO)/1000)*4/((Fmax-Fmin)/1000)) + 1 ; - status += MXL_ControlWrite(fe, RFSYN_LPF_R, E5A) ; + status += MXL_ControlWrite(fe, RFSYN_LPF_R, E5A); - // Euqation E5B - // CHCAL_EN_INIT_RF + /* Euqation E5B CHCAL_EN_INIT_RF */ status += MXL_ControlWrite(fe, CHCAL_EN_INT_RF, ((E5 == 0) ? 1 : 0)); - //if (E5 == 0) - // status += MXL_ControlWrite(fe, CHCAL_EN_INT_RF, 1); - //else - // status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, E5) ; - - // - // Set TG Synth - // - // Look-Up table implementation for: - // TG_LO_DIVVAL - // TG_LO_SELVAL - // - // Set divider_val, Fmax, Fmix to use in Equations - if (state->TG_LO < 33000000UL) { + /*if (E5 == 0) + * status += MXL_ControlWrite(fe, CHCAL_EN_INT_RF, 1); + *else + * status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, E5); + */ + + /* + * Set TG Synth + * + * Look-Up table implementation for: + * TG_LO_DIVVAL + * TG_LO_SELVAL + * + * Set divider_val, Fmax, Fmix to use in Equations + */ + if (state->TG_LO < 33000000UL) return -1; - } + FminBin = 33000000UL ; FmaxBin = 50000000UL ; if (state->TG_LO >= FminBin && state->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x6) ; - status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x0) ; + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x6); + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x0); divider_val = 36 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -2893,8 +2683,8 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 50000000UL ; FmaxBin = 67000000UL ; if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x1) ; - status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x0) ; + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x1); + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x0); divider_val = 24 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -2902,8 +2692,8 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 67000000UL ; FmaxBin = 100000000UL ; if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0xC) ; - status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x2) ; + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0xC); + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x2); divider_val = 18 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -2911,8 +2701,8 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 100000000UL ; FmaxBin = 150000000UL ; if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x8) ; - status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x2) ; + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x8); + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x2); divider_val = 12 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -2920,8 +2710,8 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 150000000UL ; FmaxBin = 200000000UL ; if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x0) ; - status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x2) ; + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x0); + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x2); divider_val = 8 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -2929,8 +2719,8 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 200000000UL ; FmaxBin = 300000000UL ; if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x8) ; - status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x3) ; + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x8); + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x3); divider_val = 6 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -2938,8 +2728,8 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 300000000UL ; FmaxBin = 400000000UL ; if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x0) ; - status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x3) ; + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x0); + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x3); divider_val = 4 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -2947,8 +2737,8 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 400000000UL ; FmaxBin = 600000000UL ; if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x8) ; - status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x7) ; + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x8); + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x7); divider_val = 3 ; Fmax = FmaxBin ; Fmin = FminBin ; @@ -2956,682 +2746,608 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) FminBin = 600000000UL ; FmaxBin = 900000000UL ; if (state->TG_LO > FminBin && state->TG_LO <= FmaxBin) { - status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x0) ; - status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x7) ; + status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x0); + status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x7); divider_val = 2 ; Fmax = FmaxBin ; Fmin = FminBin ; } - // TG_DIV_VAL - tg_divval = (state->TG_LO*divider_val/100000) - *(MXL_Ceiling(state->Fxtal,1000000) * 100) / (state->Fxtal/1000) ; - status += MXL_ControlWrite(fe, TG_DIV_VAL, tg_divval) ; + /* TG_DIV_VAL */ + tg_divval = (state->TG_LO*divider_val/100000) * + (MXL_Ceiling(state->Fxtal, 1000000) * 100) / + (state->Fxtal/1000); + + status += MXL_ControlWrite(fe, TG_DIV_VAL, tg_divval); if (state->TG_LO > 600000000UL) - status += MXL_ControlWrite(fe, TG_DIV_VAL, tg_divval + 1 ) ; + status += MXL_ControlWrite(fe, TG_DIV_VAL, tg_divval + 1); Fmax = 1800000000UL ; Fmin = 1200000000UL ; + /* prevent overflow of 32 bit unsigned integer, use + * following equation. Edit for v2.6.4 + */ + /* Fref_TF = Fref_TG * 1000 */ + Fref_TG = (state->Fxtal/1000) / MXL_Ceiling(state->Fxtal, 1000000); - - // to prevent overflow of 32 bit unsigned integer, use following equation. Edit for v2.6.4 - Fref_TG = (state->Fxtal/1000)/ MXL_Ceiling(state->Fxtal, 1000000) ; // Fref_TF = Fref_TG*1000 - - Fvco = (state->TG_LO/10000) * divider_val * Fref_TG; //Fvco = Fvco/10 + /* Fvco = Fvco/10 */ + Fvco = (state->TG_LO/10000) * divider_val * Fref_TG; tg_lo = (((Fmax/10 - Fvco)/100)*32) / ((Fmax-Fmin)/1000)+8; - //below equation is same as above but much harder to debug. - //tg_lo = ( ((Fmax/10000 * Xtal_Int)/100) - ((state->TG_LO/10000)*divider_val*(state->Fxtal/10000)/100) )*32/((Fmax-Fmin)/10000 * Xtal_Int/100) + 8 ; - - - status += MXL_ControlWrite(fe, TG_VCO_BIAS , tg_lo) ; - + /* below equation is same as above but much harder to debug. + * tg_lo = ( ((Fmax/10000 * Xtal_Int)/100) - + * ((state->TG_LO/10000)*divider_val * + * (state->Fxtal/10000)/100) )*32/((Fmax-Fmin)/10000 * + * Xtal_Int/100) + 8; + */ + status += MXL_ControlWrite(fe, TG_VCO_BIAS , tg_lo); - //add for 2.6.5 - //Special setting for QAM - if(state->Mod_Type == MXL_QAM) - { - if(state->RF_IN < 680000000) - status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3) ; - else - status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 2) ; + /* add for 2.6.5 Special setting for QAM */ + if (state->Mod_Type == MXL_QAM) { + if (state->RF_IN < 680000000) + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3); + else + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 2); } - - //remove 20.48MHz setting for 2.6.10 - - // - // Off Chip Tracking Filter Control - // - if (state->TF_Type == MXL_TF_OFF) // Tracking Filter Off State; turn off all the banks - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; - - status += MXL_SetGPIO(fe, 3, 1) ; // turn off Bank 1 - status += MXL_SetGPIO(fe, 1, 1) ; // turn off Bank 2 - status += MXL_SetGPIO(fe, 4, 1) ; // turn off Bank 3 + /* Off Chip Tracking Filter Control */ + if (state->TF_Type == MXL_TF_OFF) { + /* Tracking Filter Off State; turn off all the banks */ + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 3, 1); /* Bank1 Off */ + status += MXL_SetGPIO(fe, 1, 1); /* Bank2 Off */ + status += MXL_SetGPIO(fe, 4, 1); /* Bank3 Off */ } - if (state->TF_Type == MXL_TF_C) // Tracking Filter type C - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; - status += MXL_ControlWrite(fe, DAC_DIN_A, 0) ; - - if (state->RF_IN >= 43000000 && state->RF_IN < 150000000) - { - - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - status += MXL_SetGPIO(fe, 3, 0) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank3 Off - } - if (state->RF_IN >= 150000000 && state->RF_IN < 280000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank3 Off - } - if (state->RF_IN >= 280000000 && state->RF_IN < 360000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 4, 0) ; // Bank3 On - } - if (state->RF_IN >= 360000000 && state->RF_IN < 560000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank3 On - } - if (state->RF_IN >= 560000000 && state->RF_IN < 580000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_ControlWrite(fe, DAC_DIN_B, 29) ; - status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank3 On - } - if (state->RF_IN >= 580000000 && state->RF_IN < 630000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank3 On - } - if (state->RF_IN >= 630000000 && state->RF_IN < 700000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_ControlWrite(fe, DAC_DIN_B, 16) ; - status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank3 Off - } - if (state->RF_IN >= 700000000 && state->RF_IN < 760000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_ControlWrite(fe, DAC_DIN_B, 7) ; - status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank3 Off - } - if (state->RF_IN >= 760000000 && state->RF_IN <= 900000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - status += MXL_SetGPIO(fe, 3, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank3 Off + if (state->TF_Type == MXL_TF_C) /* Tracking Filter type C */ { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1); + status += MXL_ControlWrite(fe, DAC_DIN_A, 0); + + if (state->RF_IN >= 43000000 && state->RF_IN < 150000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_ControlWrite(fe, DAC_DIN_B, 0); + status += MXL_SetGPIO(fe, 3, 0); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 4, 1); + } + if (state->RF_IN >= 150000000 && state->RF_IN < 280000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_ControlWrite(fe, DAC_DIN_B, 0); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 4, 1); + } + if (state->RF_IN >= 280000000 && state->RF_IN < 360000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_ControlWrite(fe, DAC_DIN_B, 0); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 4, 0); + } + if (state->RF_IN >= 360000000 && state->RF_IN < 560000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_ControlWrite(fe, DAC_DIN_B, 0); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 4, 0); + } + if (state->RF_IN >= 560000000 && state->RF_IN < 580000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1); + status += MXL_ControlWrite(fe, DAC_DIN_B, 29); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 4, 0); + } + if (state->RF_IN >= 580000000 && state->RF_IN < 630000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1); + status += MXL_ControlWrite(fe, DAC_DIN_B, 0); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 4, 0); + } + if (state->RF_IN >= 630000000 && state->RF_IN < 700000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1); + status += MXL_ControlWrite(fe, DAC_DIN_B, 16); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 4, 1); + } + if (state->RF_IN >= 700000000 && state->RF_IN < 760000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1); + status += MXL_ControlWrite(fe, DAC_DIN_B, 7); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 4, 1); + } + if (state->RF_IN >= 760000000 && state->RF_IN <= 900000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1); + status += MXL_ControlWrite(fe, DAC_DIN_B, 0); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 4, 1); } } - if (state->TF_Type == MXL_TF_C_H) // Tracking Filter type C-H for Hauppauge only - { - printk("%s() CH filter\n", __func__); - status += MXL_ControlWrite(fe, DAC_DIN_A, 0) ; - - if (state->RF_IN >= 43000000 && state->RF_IN < 150000000) - { - - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(fe, 3, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank3 Off - } - if (state->RF_IN >= 150000000 && state->RF_IN < 280000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 1, 1) ; // Bank3 Off - } - if (state->RF_IN >= 280000000 && state->RF_IN < 360000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 1, 0) ; // Bank3 On - } - if (state->RF_IN >= 360000000 && state->RF_IN < 560000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank3 On - } - if (state->RF_IN >= 560000000 && state->RF_IN < 580000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank3 On - } - if (state->RF_IN >= 580000000 && state->RF_IN < 630000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank3 On - } - if (state->RF_IN >= 630000000 && state->RF_IN < 700000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank3 Off - } - if (state->RF_IN >= 700000000 && state->RF_IN < 760000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank3 Off - } - if (state->RF_IN >= 760000000 && state->RF_IN <= 900000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank3 Off + if (state->TF_Type == MXL_TF_C_H) { + + /* Tracking Filter type C-H for Hauppauge only */ + status += MXL_ControlWrite(fe, DAC_DIN_A, 0); + + if (state->RF_IN >= 43000000 && state->RF_IN < 150000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 1); + } + if (state->RF_IN >= 150000000 && state->RF_IN < 280000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 3, 0); + status += MXL_SetGPIO(fe, 1, 1); + } + if (state->RF_IN >= 280000000 && state->RF_IN < 360000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 3, 0); + status += MXL_SetGPIO(fe, 1, 0); + } + if (state->RF_IN >= 360000000 && state->RF_IN < 560000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 0); + } + if (state->RF_IN >= 560000000 && state->RF_IN < 580000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 0); + } + if (state->RF_IN >= 580000000 && state->RF_IN < 630000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 0); + } + if (state->RF_IN >= 630000000 && state->RF_IN < 700000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 1); + } + if (state->RF_IN >= 700000000 && state->RF_IN < 760000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 1); + } + if (state->RF_IN >= 760000000 && state->RF_IN <= 900000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 1); } } - if (state->TF_Type == MXL_TF_D) // Tracking Filter type D - { - status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - - if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) - { - - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 250000000 && state->RF_IN < 310000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 310000000 && state->RF_IN < 360000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 360000000 && state->RF_IN < 470000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 640000000 && state->RF_IN <= 900000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off + if (state->TF_Type == MXL_TF_D) { /* Tracking Filter type D */ + + status += MXL_ControlWrite(fe, DAC_DIN_B, 0); + + if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 250000000 && state->RF_IN < 310000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 310000000 && state->RF_IN < 360000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 360000000 && state->RF_IN < 470000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 640000000 && state->RF_IN <= 900000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); } } - - if (state->TF_Type == MXL_TF_D_L) // Tracking Filter type D-L for Lumanate ONLY change for 2.6.3 - { - status += MXL_ControlWrite(fe, DAC_DIN_A, 0) ; - - // if UHF and terrestrial => Turn off Tracking Filter - if (state->RF_IN >= 471000000 && (state->RF_IN - 471000000)%6000000 != 0) - { - // Turn off all the banks - status += MXL_SetGPIO(fe, 3, 1) ; - status += MXL_SetGPIO(fe, 1, 1) ; - status += MXL_SetGPIO(fe, 4, 1) ; - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; - - status += MXL_ControlWrite(fe, AGC_IF, 10) ; - } - - else // if VHF or cable => Turn on Tracking Filter - { - if (state->RF_IN >= 43000000 && state->RF_IN < 140000000) - { - - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 Off + if (state->TF_Type == MXL_TF_D_L) { + + /* Tracking Filter type D-L for Lumanate ONLY change 2.6.3 */ + status += MXL_ControlWrite(fe, DAC_DIN_A, 0); + + /* if UHF and terrestrial => Turn off Tracking Filter */ + if (state->RF_IN >= 471000000 && + (state->RF_IN - 471000000)%6000000 != 0) { + /* Turn off all the banks */ + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_ControlWrite(fe, AGC_IF, 10); + } else { + /* if VHF or cable => Turn on Tracking Filter */ + if (state->RF_IN >= 43000000 && + state->RF_IN < 140000000) { + + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 0); } - if (state->RF_IN >= 140000000 && state->RF_IN < 240000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 Off + if (state->RF_IN >= 140000000 && + state->RF_IN < 240000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 0); } - if (state->RF_IN >= 240000000 && state->RF_IN < 340000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 Off + if (state->RF_IN >= 240000000 && + state->RF_IN < 340000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 0); } - if (state->RF_IN >= 340000000 && state->RF_IN < 430000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 On + if (state->RF_IN >= 340000000 && + state->RF_IN < 430000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); } - if (state->RF_IN >= 430000000 && state->RF_IN < 470000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 On + if (state->RF_IN >= 430000000 && + state->RF_IN < 470000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); } - if (state->RF_IN >= 470000000 && state->RF_IN < 570000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 On + if (state->RF_IN >= 470000000 && + state->RF_IN < 570000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); } - if (state->RF_IN >= 570000000 && state->RF_IN < 620000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Offq + if (state->RF_IN >= 570000000 && + state->RF_IN < 620000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); } - if (state->RF_IN >= 620000000 && state->RF_IN < 760000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off + if (state->RF_IN >= 620000000 && + state->RF_IN < 760000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); } - if (state->RF_IN >= 760000000 && state->RF_IN <= 900000000) - { - status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off + if (state->RF_IN >= 760000000 && + state->RF_IN <= 900000000) { + status += MXL_ControlWrite(fe, DAC_A_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); } } } - if (state->TF_Type == MXL_TF_E) // Tracking Filter type E - { - status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - - if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) - { - - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 250000000 && state->RF_IN < 310000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 310000000 && state->RF_IN < 360000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 360000000 && state->RF_IN < 470000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 640000000 && state->RF_IN <= 900000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off + if (state->TF_Type == MXL_TF_E) /* Tracking Filter type E */ { + + status += MXL_ControlWrite(fe, DAC_DIN_B, 0); + + if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 250000000 && state->RF_IN < 310000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 310000000 && state->RF_IN < 360000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 360000000 && state->RF_IN < 470000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 640000000 && state->RF_IN <= 900000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); } } - if (state->TF_Type == MXL_TF_F) // Tracking Filter type F - { - status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - - if (state->RF_IN >= 43000000 && state->RF_IN < 160000000) - { - - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 160000000 && state->RF_IN < 210000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 210000000 && state->RF_IN < 300000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 300000000 && state->RF_IN < 390000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 390000000 && state->RF_IN < 515000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 515000000 && state->RF_IN < 650000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 650000000 && state->RF_IN <= 900000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off + if (state->TF_Type == MXL_TF_F) { + + /* Tracking Filter type F */ + status += MXL_ControlWrite(fe, DAC_DIN_B, 0); + + if (state->RF_IN >= 43000000 && state->RF_IN < 160000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 160000000 && state->RF_IN < 210000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 210000000 && state->RF_IN < 300000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 300000000 && state->RF_IN < 390000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 390000000 && state->RF_IN < 515000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 515000000 && state->RF_IN < 650000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 650000000 && state->RF_IN <= 900000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); } } - if (state->TF_Type == MXL_TF_E_2) // Tracking Filter type E_2 - { - status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - - if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) - { - - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 250000000 && state->RF_IN < 350000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 400000000 && state->RF_IN < 570000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 570000000 && state->RF_IN < 770000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 770000000 && state->RF_IN <= 900000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off + if (state->TF_Type == MXL_TF_E_2) { + + /* Tracking Filter type E_2 */ + status += MXL_ControlWrite(fe, DAC_DIN_B, 0); + + if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 250000000 && state->RF_IN < 350000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 400000000 && state->RF_IN < 570000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 570000000 && state->RF_IN < 770000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 770000000 && state->RF_IN <= 900000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); } } - if (state->TF_Type == MXL_TF_G) // Tracking Filter type G add for v2.6.8 - { - status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - - if (state->RF_IN >= 50000000 && state->RF_IN < 190000000) - { - - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 190000000 && state->RF_IN < 280000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 280000000 && state->RF_IN < 350000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 400000000 && state->RF_IN < 470000000) //modified for 2.6.11 - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 640000000 && state->RF_IN < 820000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 820000000 && state->RF_IN <= 900000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off + if (state->TF_Type == MXL_TF_G) { + + /* Tracking Filter type G add for v2.6.8 */ + status += MXL_ControlWrite(fe, DAC_DIN_B, 0); + + if (state->RF_IN >= 50000000 && state->RF_IN < 190000000) { + + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 190000000 && state->RF_IN < 280000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 280000000 && state->RF_IN < 350000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 400000000 && state->RF_IN < 470000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 470000000 && state->RF_IN < 640000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 640000000 && state->RF_IN < 820000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 820000000 && state->RF_IN <= 900000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); } } - if (state->TF_Type == MXL_TF_E_NA) // Tracking Filter type E-NA for Empia ONLY change for 2.6.8 - { - status += MXL_ControlWrite(fe, DAC_DIN_B, 0) ; - - // if UHF and terrestrial=> Turn off Tracking Filter - if (state->RF_IN >= 471000000 && (state->RF_IN - 471000000)%6000000 != 0) - { - // Turn off all the banks - status += MXL_SetGPIO(fe, 3, 1) ; - status += MXL_SetGPIO(fe, 1, 1) ; - status += MXL_SetGPIO(fe, 4, 1) ; - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; - - //2.6.12 - //Turn on RSSI - status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1) ; - status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1) ; - status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1) ; - status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1) ; - - // RSSI reference point - status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5) ; - status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3) ; - status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 2) ; - - - //status += MXL_ControlWrite(fe, AGC_IF, 10) ; //doesn't matter since RSSI is turn on - - //following parameter is from analog OTA mode, can be change to seek better performance - status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3) ; - } - - else //if VHF or Cable => Turn on Tracking Filter - { - //2.6.12 - //Turn off RSSI - status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0) ; - - //change back from above condition - status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 5) ; - - - if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) - { - - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 0) ; // Bank1 On - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 250000000 && state->RF_IN < 350000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off - } - if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 0) ; // Bank2 On - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 400000000 && state->RF_IN < 570000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0) ; // Bank4 Off - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 570000000 && state->RF_IN < 770000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 0) ; // Bank3 On - } - if (state->RF_IN >= 770000000 && state->RF_IN <= 900000000) - { - status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1) ; // Bank4 On - status += MXL_SetGPIO(fe, 4, 1) ; // Bank1 Off - status += MXL_SetGPIO(fe, 1, 1) ; // Bank2 Off - status += MXL_SetGPIO(fe, 3, 1) ; // Bank3 Off + if (state->TF_Type == MXL_TF_E_NA) { + + /* Tracking Filter type E-NA for Empia ONLY change for 2.6.8 */ + status += MXL_ControlWrite(fe, DAC_DIN_B, 0); + + /* if UHF and terrestrial=> Turn off Tracking Filter */ + if (state->RF_IN >= 471000000 && + (state->RF_IN - 471000000)%6000000 != 0) { + + /* Turn off all the banks */ + status += MXL_SetGPIO(fe, 3, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + + /* 2.6.12 Turn on RSSI */ + status += MXL_ControlWrite(fe, SEQ_EXTSYNTHCALIF, 1); + status += MXL_ControlWrite(fe, SEQ_EXTDCCAL, 1); + status += MXL_ControlWrite(fe, AGC_EN_RSSI, 1); + status += MXL_ControlWrite(fe, RFA_ENCLKRFAGC, 1); + + /* RSSI reference point */ + status += MXL_ControlWrite(fe, RFA_RSSI_REFH, 5); + status += MXL_ControlWrite(fe, RFA_RSSI_REF, 3); + status += MXL_ControlWrite(fe, RFA_RSSI_REFL, 2); + + /* following parameter is from analog OTA mode, + * can be change to seek better performance */ + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 3); + } else { + /* if VHF or Cable => Turn on Tracking Filter */ + + /* 2.6.12 Turn off RSSI */ + status += MXL_ControlWrite(fe, AGC_EN_RSSI, 0); + + /* change back from above condition */ + status += MXL_ControlWrite(fe, RFSYN_CHP_GAIN, 5); + + + if (state->RF_IN >= 43000000 && state->RF_IN < 174000000) { + + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 174000000 && state->RF_IN < 250000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 0); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 250000000 && state->RF_IN < 350000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 1); + } + if (state->RF_IN >= 350000000 && state->RF_IN < 400000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 0); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 400000000 && state->RF_IN < 570000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 0); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 570000000 && state->RF_IN < 770000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 0); + } + if (state->RF_IN >= 770000000 && state->RF_IN <= 900000000) { + status += MXL_ControlWrite(fe, DAC_B_ENABLE, 1); + status += MXL_SetGPIO(fe, 4, 1); + status += MXL_SetGPIO(fe, 1, 1); + status += MXL_SetGPIO(fe, 3, 1); } } } @@ -3679,72 +3395,24 @@ u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val) return status; } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL_ControlWrite // -// // -// Description: Update control name value // -// // -// Globals: // -// NONE // -// // -// Functions used: // -// MXL_ControlWrite( Tuner, controlName, value, Group ) // -// // -// Inputs: // -// Tuner : Tuner structure // -// ControlName : Control name to be updated // -// value : Value to be written // -// // -// Outputs: // -// Tuner : Tuner structure defined at higher level // -// // -// Return: // -// 0 : Successful write // -// >0 : Value exceed maximum allowed for control number // -// // -/////////////////////////////////////////////////////////////////////////////// u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value) { u16 status = 0; /* Will write ALL Matching Control Name */ - status += MXL_ControlWrite_Group(fe, ControlNum, value, 1); /* Write Matching INIT Control */ - status += MXL_ControlWrite_Group(fe, ControlNum, value, 2); /* Write Matching CH Control */ + /* Write Matching INIT Control */ + status += MXL_ControlWrite_Group(fe, ControlNum, value, 1); + /* Write Matching CH Control */ + status += MXL_ControlWrite_Group(fe, ControlNum, value, 2); #ifdef _MXL_INTERNAL - status += MXL_ControlWrite_Group(fe, ControlNum, value, 3); /* Write Matching MXL Control */ + /* Write Matching MXL Control */ + status += MXL_ControlWrite_Group(fe, ControlNum, value, 3); #endif return status; } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL_ControlWrite // -// // -// Description: Update control name value // -// // -// Globals: // -// NONE // -// // -// Functions used: // -// strcmp // -// // -// Inputs: // -// Tuner_struct: structure defined at higher level // -// ControlName : Control Name // -// value : Value Assigned to Control Name // -// controlGroup : Control Register Group // -// // -// Outputs: // -// NONE // -// // -// Return: // -// 0 : Successful write // -// 1 : Value exceed maximum allowed for control name // -// 2 : Control name not found // -// // -/////////////////////////////////////////////////////////////////////////////// -u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u16 controlGroup) +u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, + u16 controlGroup) { struct mxl5005s_state *state = fe->tuner_priv; u16 i, j, k; @@ -3763,13 +3431,12 @@ u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u state->Init_Ctrl[i].val[j] = (u8)((value >> j) & 0x01); MXL_RegWriteBit(fe, (u8)(state->Init_Ctrl[i].addr[j]), (u8)(state->Init_Ctrl[i].bit[j]), - (u8)((value>>j) & 0x01) ); + (u8)((value>>j) & 0x01)); } ctrlVal = 0; for (k = 0; k < state->Init_Ctrl[i].size; k++) ctrlVal += state->Init_Ctrl[i].val[k] * (1 << k); - } - else + } else return -1; } } @@ -3778,7 +3445,7 @@ u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u for (i = 0; i < state->CH_Ctrl_Num; i++) { - if (controlNum == state->CH_Ctrl[i].Ctrl_Num ) { + if (controlNum == state->CH_Ctrl[i].Ctrl_Num) { highLimit = 1 << state->CH_Ctrl[i].size; if (value < highLimit) { @@ -3786,13 +3453,12 @@ u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u state->CH_Ctrl[i].val[j] = (u8)((value >> j) & 0x01); MXL_RegWriteBit(fe, (u8)(state->CH_Ctrl[i].addr[j]), (u8)(state->CH_Ctrl[i].bit[j]), - (u8)((value>>j) & 0x01) ); + (u8)((value>>j) & 0x01)); } ctrlVal = 0; for (k = 0; k < state->CH_Ctrl[i].size; k++) ctrlVal += state->CH_Ctrl[i].val[k] * (1 << k); - } - else + } else return -1; } } @@ -3802,21 +3468,20 @@ u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u for (i = 0; i < state->MXL_Ctrl_Num; i++) { - if (controlNum == state->MXL_Ctrl[i].Ctrl_Num ) { + if (controlNum == state->MXL_Ctrl[i].Ctrl_Num) { - highLimit = (1 << state->MXL_Ctrl[i].size) ; + highLimit = (1 << state->MXL_Ctrl[i].size); if (value < highLimit) { for (j = 0; j < state->MXL_Ctrl[i].size; j++) { state->MXL_Ctrl[i].val[j] = (u8)((value >> j) & 0x01); MXL_RegWriteBit(fe, (u8)(state->MXL_Ctrl[i].addr[j]), (u8)(state->MXL_Ctrl[i].bit[j]), - (u8)((value>>j) & 0x01) ); + (u8)((value>>j) & 0x01)); } ctrlVal = 0; - for(k = 0; k < state->MXL_Ctrl[i].size; k++) + for (k = 0; k < state->MXL_Ctrl[i].size; k++) ctrlVal += state->MXL_Ctrl[i].val[k] * (1 << k); - } - else + } else return -1; } } @@ -3825,31 +3490,6 @@ u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u return 0 ; /* successful return */ } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL_RegWrite // -// // -// Description: Update tuner register value // -// // -// Globals: // -// NONE // -// // -// Functions used: // -// NONE // -// // -// Inputs: // -// Tuner_struct: structure defined at higher level // -// RegNum : Register address to be assigned a value // -// RegVal : Register value to write // -// // -// Outputs: // -// NONE // -// // -// Return: // -// 0 : Successful write // -// -1 : Invalid Register Address // -// // -/////////////////////////////////////////////////////////////////////////////// u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) { struct mxl5005s_state *state = fe->tuner_priv; @@ -3865,37 +3505,13 @@ u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) return 1; } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL_RegRead // -// // -// Description: Retrieve tuner register value // -// // -// Globals: // -// NONE // -// // -// Functions used: // -// NONE // -// // -// Inputs: // -// Tuner_struct: structure defined at higher level // -// RegNum : Register address to be assigned a value // -// // -// Outputs: // -// RegVal : Retrieved register value // -// // -// Return: // -// 0 : Successful read // -// -1 : Invalid Register Address // -// // -/////////////////////////////////////////////////////////////////////////////// u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) { struct mxl5005s_state *state = fe->tuner_priv; int i ; for (i = 0; i < 104; i++) { - if (RegNum == state->TunerRegs[i].Reg_Num ) { + if (RegNum == state->TunerRegs[i].Reg_Num) { *RegVal = (u8)(state->TunerRegs[i].Reg_Val); return 0; } @@ -3904,27 +3520,6 @@ u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) return 1; } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL_ControlRead // -// // -// Description: Retrieve the control value based on the control name // -// // -// Globals: // -// NONE // -// // -// Inputs: // -// Tuner_struct : structure defined at higher level // -// ControlName : Control Name // -// // -// Outputs: // -// value : returned control value // -// // -// Return: // -// 0 : Successful read // -// -1 : Invalid control name // -// // -/////////////////////////////////////////////////////////////////////////////// u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value) { struct mxl5005s_state *state = fe->tuner_priv; @@ -3937,7 +3532,7 @@ u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value) ctrlVal = 0; for (k = 0; k < state->Init_Ctrl[i].size; k++) - ctrlVal += state->Init_Ctrl[i].val[k] * (1 << k); + ctrlVal += state->Init_Ctrl[i].val[k] * (1<tuner_priv; u16 i, j, k ; @@ -4004,7 +3577,7 @@ u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int for (i = 0; i < state->Init_Ctrl_Num ; i++) { - if ( controlNum == state->Init_Ctrl[i].Ctrl_Num ) { + if (controlNum == state->Init_Ctrl[i].Ctrl_Num) { Count = 1; RegNum[0] = (u8)(state->Init_Ctrl[i].addr[0]); @@ -4013,9 +3586,10 @@ u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int for (j = 0; j < Count; j++) { - if (state->Init_Ctrl[i].addr[k] != RegNum[j]) { + if (state->Init_Ctrl[i].addr[k] != + RegNum[j]) { - Count ++; + Count++; RegNum[Count-1] = (u8)(state->Init_Ctrl[i].addr[k]); } @@ -4028,18 +3602,19 @@ u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int } for (i = 0; i < state->CH_Ctrl_Num ; i++) { - if ( controlNum == state->CH_Ctrl[i].Ctrl_Num ) { + if (controlNum == state->CH_Ctrl[i].Ctrl_Num) { Count = 1; RegNum[0] = (u8)(state->CH_Ctrl[i].addr[0]); for (k = 1; k < state->CH_Ctrl[i].size; k++) { - for (j= 0; jCH_Ctrl[i].addr[k] != RegNum[j]) { + if (state->CH_Ctrl[i].addr[k] != + RegNum[j]) { - Count ++; + Count++; RegNum[Count-1] = (u8)(state->CH_Ctrl[i].addr[k]); } @@ -4052,18 +3627,19 @@ u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int #ifdef _MXL_INTERNAL for (i = 0; i < state->MXL_Ctrl_Num ; i++) { - if ( controlNum == state->MXL_Ctrl[i].Ctrl_Num ) { + if (controlNum == state->MXL_Ctrl[i].Ctrl_Num) { Count = 1; RegNum[0] = (u8)(state->MXL_Ctrl[i].addr[0]); for (k = 1; k < state->MXL_Ctrl[i].size; k++) { - for (j = 0; jMXL_Ctrl[i].addr[k] != RegNum[j]) { + if (state->MXL_Ctrl[i].addr[k] != + RegNum[j]) { - Count ++; + Count++; RegNum[Count-1] = (u8)state->MXL_Ctrl[i].addr[k]; } @@ -4078,29 +3654,6 @@ u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, int return 1; } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL_RegWriteBit // -// // -// Description: Write a register for specified register address, // -// register bit and register bit value // -// // -// Globals: // -// NONE // -// // -// Inputs: // -// Tuner_struct : structure defined at higher level // -// address : register address // -// bit : register bit number // -// bitVal : register bit value // -// // -// Outputs: // -// NONE // -// // -// Return: // -// NONE // -// // -/////////////////////////////////////////////////////////////////////////////// void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4125,38 +3678,14 @@ void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal) } } -/////////////////////////////////////////////////////////////////////////////// -// // -// Function: MXL_Ceiling // -// // -// Description: Complete to closest increment of resolution // -// // -// Globals: // -// NONE // -// // -// Functions used: // -// NONE // -// // -// Inputs: // -// value : Input number to compute // -// resolution : Increment step // -// // -// Outputs: // -// NONE // -// // -// Return: // -// Computed value // -// // -/////////////////////////////////////////////////////////////////////////////// u32 MXL_Ceiling(u32 value, u32 resolution) { return (value/resolution + (value % resolution > 0 ? 1 : 0)); } -// -// Retrieve the Initialzation Registers -// -u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) +/* Retrieve the Initialzation Registers */ +u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum, + u8 *RegVal, int *count) { u16 status = 0; int i ; @@ -4178,21 +3707,24 @@ u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *c return status; } -u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) +u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, + int *count) { u16 status = 0; int i ; -//add 77, 166, 167, 168 register for 2.6.12 +/* add 77, 166, 167, 168 register for 2.6.12 */ #ifdef _MXL_PRODUCTION u8 RegAddr[] = {14, 15, 16, 17, 22, 43, 65, 68, 69, 70, 73, 92, 93, 106, 107, 108, 109, 110, 111, 112, 136, 138, 149, 77, 166, 167, 168 } ; #else u8 RegAddr[] = {14, 15, 16, 17, 22, 43, 68, 69, 70, 73, 92, 93, 106, 107, 108, 109, 110, 111, 112, 136, 138, 149, 77, 166, 167, 168 } ; - //u8 RegAddr[171]; - //for (i=0; i<=170; i++) - // RegAddr[i] = i; + /* + u8 RegAddr[171]; + for (i = 0; i <= 170; i++) + RegAddr[i] = i; + */ #endif *count = sizeof(RegAddr) / sizeof(u8); @@ -4205,7 +3737,8 @@ u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *cou return status; } -u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) +u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, + int *count) { u16 status = 0; int i; @@ -4222,7 +3755,8 @@ u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, i return status; } -u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 * RegNum, u8 *RegVal, int *count) +u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, + int *count) { u16 status = 0; int i; @@ -4267,23 +3801,28 @@ u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range) status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_OUT, 1); status += MXL_ControlWrite(fe, RFSYN_RF_DIV_BIAS, 1); status += MXL_ControlWrite(fe, DN_SEL_FREQ, 0); - if (state->Mode == 0 && state->IF_Mode == 1) /* Analog Low IF Mode */ { + if (state->Mode == 0 && state->IF_Mode == 1) { + /* Analog Low IF Mode */ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 56); - status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 180224); + status += MXL_ControlWrite(fe, + CHCAL_FRAC_MOD_RF, 180224); } - if (state->Mode == 0 && state->IF_Mode == 0) /* Analog Zero IF Mode */ { + if (state->Mode == 0 && state->IF_Mode == 0) { + /* Analog Zero IF Mode */ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 56); - status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 222822); + status += MXL_ControlWrite(fe, + CHCAL_FRAC_MOD_RF, 222822); } if (state->Mode == 1) /* Digital Mode */ { status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 56); - status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 229376); + status += MXL_ControlWrite(fe, + CHCAL_FRAC_MOD_RF, 229376); } } @@ -4298,23 +3837,28 @@ u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range) status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 41); - if (state->Mode == 0 && state->IF_Mode == 1) /* Analog Low IF Mode */ { + if (state->Mode == 0 && state->IF_Mode == 1) { + /* Analog Low IF Mode */ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42); - status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 206438); + status += MXL_ControlWrite(fe, + CHCAL_FRAC_MOD_RF, 206438); } - if (state->Mode == 0 && state->IF_Mode == 0) /* Analog Zero IF Mode */ { + if (state->Mode == 0 && state->IF_Mode == 0) { + /* Analog Zero IF Mode */ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42); - status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 206438); + status += MXL_ControlWrite(fe, + CHCAL_FRAC_MOD_RF, 206438); } if (state->Mode == 1) /* Digital Mode */ { status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 1); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 41); - status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 16384); + status += MXL_ControlWrite(fe, + CHCAL_FRAC_MOD_RF, 16384); } } @@ -4329,23 +3873,28 @@ u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range) status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42); - if (state->Mode == 0 && state->IF_Mode == 1) /* Analog Low IF Mode */ { + if (state->Mode == 0 && state->IF_Mode == 1) { + /* Analog Low IF Mode */ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 44); - status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 173670); + status += MXL_ControlWrite(fe, + CHCAL_FRAC_MOD_RF, 173670); } - if (state->Mode == 0 && state->IF_Mode == 0) /* Analog Zero IF Mode */ { + if (state->Mode == 0 && state->IF_Mode == 0) { + /* Analog Zero IF Mode */ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 44); - status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 173670); + status += MXL_ControlWrite(fe, + CHCAL_FRAC_MOD_RF, 173670); } if (state->Mode == 1) /* Digital Mode */ { status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 8); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 42); - status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 245760); + status += MXL_ControlWrite(fe, + CHCAL_FRAC_MOD_RF, 245760); } } @@ -4360,23 +3909,28 @@ u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range) status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27); - if (state->Mode == 0 && state->IF_Mode == 1) /* Analog Low IF Mode */ { + if (state->Mode == 0 && state->IF_Mode == 1) { + /* Analog Low IF Mode */ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27); - status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 206438); + status += MXL_ControlWrite(fe, + CHCAL_FRAC_MOD_RF, 206438); } - if (state->Mode == 0 && state->IF_Mode == 0) /* Analog Zero IF Mode */ { + if (state->Mode == 0 && state->IF_Mode == 0) { + /* Analog Zero IF Mode */ status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27); - status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 206438); + status += MXL_ControlWrite(fe, + CHCAL_FRAC_MOD_RF, 206438); } if (state->Mode == 1) /* Digital Mode */ { status += MXL_ControlWrite(fe, RFSYN_SEL_VCO_HI, 0); status += MXL_ControlWrite(fe, RFSYN_VCO_BIAS, 40); status += MXL_ControlWrite(fe, CHCAL_INT_MOD_RF, 27); - status += MXL_ControlWrite(fe, CHCAL_FRAC_MOD_RF, 212992); + status += MXL_ControlWrite(fe, + CHCAL_FRAC_MOD_RF, 212992); } } @@ -4440,7 +3994,7 @@ static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val, int latch) if (latch == 0) msg.len = 2; - dprintk(2, "%s(reg = 0x%x val = 0x%x addr = 0x%x)\n", __func__, reg, val, msg.addr); + dprintk(2, "%s(0x%x, 0x%x, 0x%x)\n", __func__, reg, val, msg.addr); if (i2c_transfer(state->i2c, &msg, 1) != 1) { printk(KERN_WARNING "mxl5005s I2C write failed\n"); @@ -4449,7 +4003,8 @@ static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val, int latch) return 0; } -int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, u8 len) +int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, + u8 len) { int ret = 0, i; @@ -4506,7 +4061,8 @@ int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth) return 0; } -int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth) +int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, + u32 bandwidth) { struct mxl5005s_state *state = fe->tuner_priv; struct mxl5005s_config *c = state->config; @@ -4553,8 +4109,8 @@ static int mxl5005s_set_params(struct dvb_frontend *fe, case QAM_AUTO: req_mode = MXL_QAM; break; } - } - else req_mode = MXL_DVBT; + } else + req_mode = MXL_DVBT; /* Change tuner for new modulation type if reqd */ if (req_mode != state->current_mode) { @@ -4655,9 +4211,11 @@ struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe, state->i2c = i2c; state->current_mode = MXL_QAM; - printk(KERN_INFO "MXL5005S: Attached at address 0x%02x\n", config->i2c_address); + printk(KERN_INFO "MXL5005S: Attached at address 0x%02x\n", + config->i2c_address); - memcpy(&fe->ops.tuner_ops, &mxl5005s_tuner_ops, sizeof(struct dvb_tuner_ops)); + memcpy(&fe->ops.tuner_ops, &mxl5005s_tuner_ops, + sizeof(struct dvb_tuner_ops)); fe->tuner_priv = state; return fe; diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h index 687cf14..0027d1e 100644 --- a/drivers/media/common/tuners/mxl5005s.h +++ b/drivers/media/common/tuners/mxl5005s.h @@ -25,8 +25,8 @@ #include -struct mxl5005s_config -{ +struct mxl5005s_config { + /* 7 bit i2c address */ u8 i2c_address; -- cgit v1.1 From 66321ba94f59ea7ba6f4451c51e171f5b30f1fd7 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 3 May 2008 13:51:11 -0300 Subject: V4L/DVB(7873): mxl5005s: Fix header includes. Ensure we have the correct .h dependencies included. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/media/common/tuners/mxl5005s.h b/drivers/media/common/tuners/mxl5005s.h index 0027d1e..396db15 100644 --- a/drivers/media/common/tuners/mxl5005s.h +++ b/drivers/media/common/tuners/mxl5005s.h @@ -23,7 +23,8 @@ #ifndef __MXL5005S_H #define __MXL5005S_H -#include +#include +#include "dvb_frontend.h" struct mxl5005s_config { -- cgit v1.1 From c6c34b1ffd40e00191e05bf0ef543a35ccd7d75d Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 3 May 2008 14:14:54 -0300 Subject: V4L/DVB(7874): mxl5005s: Fix function statics Fix function statics Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 121 +++++++++++++++++---------------- 1 file changed, 62 insertions(+), 59 deletions(-) diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index 21dca5b..9639164 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -295,32 +295,34 @@ struct mxl5005s_state { }; -u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value); -u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value); -u16 MXL_GetMasterControl(u8 *MasterReg, int state); -void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal); -u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum, +static u16 MXL_GetMasterControl(u8 *MasterReg, int state); +static u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value); +static u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value); +static void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, + u8 bitVal); +static u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count); -u32 MXL_Ceiling(u32 value, u32 resolution); -u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal); -u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal); -u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, +static u32 MXL_Ceiling(u32 value, u32 resolution); +static u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal); +static u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal); +static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u16 controlGroup); -u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val); -u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum, +static u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val); +static u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count); -u32 MXL_GetXtalInt(u32 Xtal_Freq); -u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq); -void MXL_SynthIFLO_Calc(struct dvb_frontend *fe); -void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe); -u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, +static u32 MXL_GetXtalInt(u32 Xtal_Freq); +static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq); +static void MXL_SynthIFLO_Calc(struct dvb_frontend *fe); +static void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe); +static u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count); -int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, +static int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, u8 len); -u16 MXL_IFSynthInit(struct dvb_frontend *fe); -int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, +static u16 MXL_IFSynthInit(struct dvb_frontend *fe); +static int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, + u32 bandwidth); +static int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth); -int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth); /* ---------------------------------------------------------------- * Begin: Custom code salvaged from the Realtek driver. @@ -334,14 +336,14 @@ int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth); * Revision: 080314 - original version */ -int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) +static int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) { struct mxl5005s_state *state = fe->tuner_priv; unsigned char AddrTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; unsigned char ByteTable[MXL5005S_REG_WRITING_TABLE_LEN_MAX]; int TableLen; - u32 IfDivval; + u32 IfDivval = 0; unsigned char MasterControlByte; dprintk(1, "%s() freq=%ld\n", __func__, RfFreqHz); @@ -399,7 +401,7 @@ int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) * Begin: Reference driver code found in the Realtek driver. * Copyright (c) 2008 MaxLinear */ -u16 MXL5005_RegisterInit(struct dvb_frontend *fe) +static u16 MXL5005_RegisterInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; state->TunerRegs_Num = TUNER_REGS_NUM ; @@ -719,7 +721,7 @@ u16 MXL5005_RegisterInit(struct dvb_frontend *fe) return 0 ; } -u16 MXL5005_ControlInit(struct dvb_frontend *fe) +static u16 MXL5005_ControlInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; state->Init_Ctrl_Num = INITCTRL_NUM; @@ -1659,7 +1661,7 @@ u16 MXL5005_ControlInit(struct dvb_frontend *fe) return 0 ; } -void InitTunerControls(struct dvb_frontend *fe) +static void InitTunerControls(struct dvb_frontend *fe) { MXL5005_RegisterInit(fe); MXL5005_ControlInit(fe); @@ -1668,7 +1670,7 @@ void InitTunerControls(struct dvb_frontend *fe) #endif } -u16 MXL5005_TunerConfig(struct dvb_frontend *fe, +static u16 MXL5005_TunerConfig(struct dvb_frontend *fe, u8 Mode, /* 0: Analog Mode ; 1: Digital Mode */ u8 IF_mode, /* for Analog Mode, 0: zero IF; 1: low IF */ u32 Bandwidth, /* filter channel bandwidth (6, 7, 8) */ @@ -1718,7 +1720,7 @@ u16 MXL5005_TunerConfig(struct dvb_frontend *fe, return status; } -void MXL_SynthIFLO_Calc(struct dvb_frontend *fe) +static void MXL_SynthIFLO_Calc(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; if (state->Mode == 1) /* Digital Mode */ @@ -1731,7 +1733,7 @@ void MXL_SynthIFLO_Calc(struct dvb_frontend *fe) } } -void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe) +static void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; @@ -1752,7 +1754,7 @@ void MXL_SynthRFTGLO_Calc(struct dvb_frontend *fe) } } -u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) +static u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) { u16 status = 0; @@ -1764,7 +1766,7 @@ u16 MXL_OverwriteICDefault(struct dvb_frontend *fe) return status; } -u16 MXL_BlockInit(struct dvb_frontend *fe) +static u16 MXL_BlockInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; u16 status = 0; @@ -2102,7 +2104,7 @@ u16 MXL_BlockInit(struct dvb_frontend *fe) return status; } -u16 MXL_IFSynthInit(struct dvb_frontend *fe) +static u16 MXL_IFSynthInit(struct dvb_frontend *fe) { struct mxl5005s_state *state = fe->tuner_priv; u16 status = 0 ; @@ -2306,7 +2308,7 @@ u16 MXL_IFSynthInit(struct dvb_frontend *fe) return status ; } -u32 MXL_GetXtalInt(u32 Xtal_Freq) +static u32 MXL_GetXtalInt(u32 Xtal_Freq) { if ((Xtal_Freq % 1000000) == 0) return (Xtal_Freq / 10000); @@ -2314,7 +2316,7 @@ u32 MXL_GetXtalInt(u32 Xtal_Freq) return (((Xtal_Freq / 1000000) + 1)*100); } -u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) +static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) { struct mxl5005s_state *state = fe->tuner_priv; u16 status = 0; @@ -3354,7 +3356,7 @@ u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) return status ; } -u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val) +static u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val) { u16 status = 0; @@ -3395,7 +3397,7 @@ u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val) return status; } -u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value) +static u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value) { u16 status = 0; @@ -3411,8 +3413,8 @@ u16 MXL_ControlWrite(struct dvb_frontend *fe, u16 ControlNum, u32 value) return status; } -u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, - u16 controlGroup) +static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, + u32 value, u16 controlGroup) { struct mxl5005s_state *state = fe->tuner_priv; u16 i, j, k; @@ -3490,7 +3492,7 @@ u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, return 0 ; /* successful return */ } -u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) +static u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) { struct mxl5005s_state *state = fe->tuner_priv; int i ; @@ -3505,7 +3507,7 @@ u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) return 1; } -u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) +static u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) { struct mxl5005s_state *state = fe->tuner_priv; int i ; @@ -3520,7 +3522,7 @@ u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) return 1; } -u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value) +static u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value) { struct mxl5005s_state *state = fe->tuner_priv; u32 ctrlVal ; @@ -3568,8 +3570,8 @@ u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value) return 1; } -u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, - int *count) +static u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, + u8 *RegNum, int *count) { struct mxl5005s_state *state = fe->tuner_priv; u16 i, j, k ; @@ -3654,7 +3656,8 @@ u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, u8 *RegNum, return 1; } -void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal) +static void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, + u8 bitVal) { struct mxl5005s_state *state = fe->tuner_priv; int i ; @@ -3678,13 +3681,13 @@ void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal) } } -u32 MXL_Ceiling(u32 value, u32 resolution) +static u32 MXL_Ceiling(u32 value, u32 resolution) { return (value/resolution + (value % resolution > 0 ? 1 : 0)); } /* Retrieve the Initialzation Registers */ -u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum, +static u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count) { u16 status = 0; @@ -3707,7 +3710,7 @@ u16 MXL_GetInitRegister(struct dvb_frontend *fe, u8 *RegNum, return status; } -u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, +static u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count) { u16 status = 0; @@ -3737,8 +3740,8 @@ u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, return status; } -u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, - int *count) +static u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, + u8 *RegVal, int *count) { u16 status = 0; int i; @@ -3755,8 +3758,8 @@ u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, return status; } -u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, - int *count) +static u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 *RegNum, + u8 *RegVal, int *count) { u16 status = 0; int i; @@ -3773,7 +3776,7 @@ u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, return status; } -u16 MXL_GetMasterControl(u8 *MasterReg, int state) +static u16 MXL_GetMasterControl(u8 *MasterReg, int state) { if (state == 1) /* Load_Start */ *MasterReg = 0xF3; @@ -3788,7 +3791,7 @@ u16 MXL_GetMasterControl(u8 *MasterReg, int state) } #ifdef _MXL_PRODUCTION -u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range) +static u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range) { struct mxl5005s_state *state = fe->tuner_priv; u16 status = 0 ; @@ -3937,7 +3940,7 @@ u16 MXL_VCORange_Test(struct dvb_frontend *fe, int VCO_Range) return status; } -u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis) +static u16 MXL_Hystersis_Test(struct dvb_frontend *fe, int Hystersis) { struct mxl5005s_state *state = fe->tuner_priv; u16 status = 0; @@ -4003,8 +4006,8 @@ static int mxl5005s_writereg(struct dvb_frontend *fe, u8 reg, u8 val, int latch) return 0; } -int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, - u8 len) +static int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, + u8 *datatable, u8 len) { int ret = 0, i; @@ -4025,14 +4028,14 @@ int mxl5005s_writeregs(struct dvb_frontend *fe, u8 *addrtable, u8 *datatable, return ret; } - -int mxl5005s_init(struct dvb_frontend *fe) +static int mxl5005s_init(struct dvb_frontend *fe) { dprintk(1, "%s()\n", __func__); return mxl5005s_reconfigure(fe, MXL_QAM, MXL5005S_BANDWIDTH_6MHZ); } -int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth) +static int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, + u32 bandwidth) { struct mxl5005s_state *state = fe->tuner_priv; @@ -4061,7 +4064,7 @@ int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth) return 0; } -int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, +static int mxl5005s_AssignTunerMode(struct dvb_frontend *fe, u32 mod_type, u32 bandwidth) { struct mxl5005s_state *state = fe->tuner_priv; -- cgit v1.1 From 90257e787faaf5ebfaa1839917e4dc6c5c104c14 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 3 May 2008 14:21:58 -0300 Subject: V4L/DVB(7875): mxl5005s: Remove redundant functions Remove redundant functions Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 120 --------------------------------- 1 file changed, 120 deletions(-) diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index 9639164..786f8da 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -304,7 +304,6 @@ static u16 MXL_GetCHRegister(struct dvb_frontend *fe, u8 *RegNum, u8 *RegVal, int *count); static u32 MXL_Ceiling(u32 value, u32 resolution); static u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal); -static u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal); static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, u32 value, u16 controlGroup); static u16 MXL_SetGPIO(struct dvb_frontend *fe, u8 GPIO_Num, u8 GPIO_Val); @@ -3492,21 +3491,6 @@ static u16 MXL_ControlWrite_Group(struct dvb_frontend *fe, u16 controlNum, return 0 ; /* successful return */ } -static u16 MXL_RegWrite(struct dvb_frontend *fe, u8 RegNum, u8 RegVal) -{ - struct mxl5005s_state *state = fe->tuner_priv; - int i ; - - for (i = 0; i < 104; i++) { - if (RegNum == state->TunerRegs[i].Reg_Num) { - state->TunerRegs[i].Reg_Val = RegVal; - return 0; - } - } - - return 1; -} - static u16 MXL_RegRead(struct dvb_frontend *fe, u8 RegNum, u8 *RegVal) { struct mxl5005s_state *state = fe->tuner_priv; @@ -3570,92 +3554,6 @@ static u16 MXL_ControlRead(struct dvb_frontend *fe, u16 controlNum, u32 *value) return 1; } -static u16 MXL_ControlRegRead(struct dvb_frontend *fe, u16 controlNum, - u8 *RegNum, int *count) -{ - struct mxl5005s_state *state = fe->tuner_priv; - u16 i, j, k ; - u16 Count ; - - for (i = 0; i < state->Init_Ctrl_Num ; i++) { - - if (controlNum == state->Init_Ctrl[i].Ctrl_Num) { - - Count = 1; - RegNum[0] = (u8)(state->Init_Ctrl[i].addr[0]); - - for (k = 1; k < state->Init_Ctrl[i].size; k++) { - - for (j = 0; j < Count; j++) { - - if (state->Init_Ctrl[i].addr[k] != - RegNum[j]) { - - Count++; - RegNum[Count-1] = (u8)(state->Init_Ctrl[i].addr[k]); - - } - } - - } - *count = Count; - return 0; - } - } - for (i = 0; i < state->CH_Ctrl_Num ; i++) { - - if (controlNum == state->CH_Ctrl[i].Ctrl_Num) { - - Count = 1; - RegNum[0] = (u8)(state->CH_Ctrl[i].addr[0]); - - for (k = 1; k < state->CH_Ctrl[i].size; k++) { - - for (j = 0; j < Count; j++) { - - if (state->CH_Ctrl[i].addr[k] != - RegNum[j]) { - - Count++; - RegNum[Count-1] = (u8)(state->CH_Ctrl[i].addr[k]); - - } - } - } - *count = Count; - return 0; - } - } -#ifdef _MXL_INTERNAL - for (i = 0; i < state->MXL_Ctrl_Num ; i++) { - - if (controlNum == state->MXL_Ctrl[i].Ctrl_Num) { - - Count = 1; - RegNum[0] = (u8)(state->MXL_Ctrl[i].addr[0]); - - for (k = 1; k < state->MXL_Ctrl[i].size; k++) { - - for (j = 0; j < Count; j++) { - - if (state->MXL_Ctrl[i].addr[k] != - RegNum[j]) { - - Count++; - RegNum[Count-1] = (u8)state->MXL_Ctrl[i].addr[k]; - - } - } - } - *count = Count; - return 0; - } - } -#endif - *count = 0; - return 1; -} - static void MXL_RegWriteBit(struct dvb_frontend *fe, u8 address, u8 bit, u8 bitVal) { @@ -3758,24 +3656,6 @@ static u16 MXL_GetCHRegister_ZeroIF(struct dvb_frontend *fe, u8 *RegNum, return status; } -static u16 MXL_GetCHRegister_LowIF(struct dvb_frontend *fe, u8 *RegNum, - u8 *RegVal, int *count) -{ - u16 status = 0; - int i; - - u8 RegAddr[] = { 138 }; - - *count = sizeof(RegAddr) / sizeof(u8); - - for (i = 0; i < *count; i++) { - RegNum[i] = RegAddr[i]; - status += MXL_RegRead(fe, RegNum[i], &RegVal[i]); - } - - return status; -} - static u16 MXL_GetMasterControl(u8 *MasterReg, int state) { if (state == 1) /* Load_Start */ -- cgit v1.1 From 7fa2a1462fe0a258fb629f8447f31c1b3a6d6c68 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 3 May 2008 14:25:55 -0300 Subject: V4L/DVB(7876): mxl5005s: Remove incorrect copyright holders I was informed by Jan Hoogenraad that two people needed to be removed from the original copyright comments. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index 786f8da..a32c357 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -16,8 +16,8 @@ mxl5005s_release() mxl5005s_attach() - Copyright (c) 2008 Realtek - Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper + Copyright (C) 2008 Realtek + Copyright (C) 2008 Jan Hoogenraad Functions: mxl5005s_SetRfFreqHz() @@ -325,8 +325,8 @@ static int mxl5005s_reconfigure(struct dvb_frontend *fe, u32 mod_type, /* ---------------------------------------------------------------- * Begin: Custom code salvaged from the Realtek driver. - * Copyright (c) 2008 Realtek - * Copyright (c) 2008 Jan Hoogenraad, Barnaby Shearer, Andy Hasper + * Copyright (C) 2008 Realtek + * Copyright (C) 2008 Jan Hoogenraad * This code is placed under the terms of the GNU General Public License * * Released by Realtek under GPLv2. @@ -398,7 +398,7 @@ static int mxl5005s_SetRfFreqHz(struct dvb_frontend *fe, unsigned long RfFreqHz) /* ---------------------------------------------------------------- * Begin: Reference driver code found in the Realtek driver. - * Copyright (c) 2008 MaxLinear + * Copyright (C) 2008 MaxLinear */ static u16 MXL5005_RegisterInit(struct dvb_frontend *fe) { -- cgit v1.1 From 77ad55ec2159735b1b88a006a90f8dd2ffe291ca Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 3 May 2008 14:28:43 -0300 Subject: V4L/DVB(7877): mxl5005s: Ensure debug is off Ensure debug is off Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/mxl5005s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/common/tuners/mxl5005s.c b/drivers/media/common/tuners/mxl5005s.c index a32c357..5d05b53 100644 --- a/drivers/media/common/tuners/mxl5005s.c +++ b/drivers/media/common/tuners/mxl5005s.c @@ -66,7 +66,7 @@ #include "dvb_frontend.h" #include "mxl5005s.h" -static int debug = 2; +static int debug; #define dprintk(level, arg...) do { \ if (level <= debug) \ -- cgit v1.1 From 9426954277aa57e0417d89bfe3e0964d6901cfa3 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 8 May 2008 12:14:40 -0300 Subject: V4L/DVB(7878): mxl55005s: Makefile and Kconfig additions Makefile and Kconfig additions Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/Kconfig | 7 +++++++ drivers/media/common/tuners/Makefile | 1 + 2 files changed, 8 insertions(+) diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index 10f12ba..394cb05 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig @@ -139,4 +139,11 @@ config MEDIA_TUNER_XC5000 This device is only used inside a SiP called togther with a demodulator for now. +config MEDIA_TUNER_MXL5005S + tristate "MaxLinear MSL5005S silicon tuner" + depends on I2C + default m if DVB_FE_CUSTOMISE + help + A driver for the silicon tuner MXL5005S from MaxLinear. + endif # MEDIA_TUNER_CUSTOMIZE diff --git a/drivers/media/common/tuners/Makefile b/drivers/media/common/tuners/Makefile index 236d9932..55f7e67 100644 --- a/drivers/media/common/tuners/Makefile +++ b/drivers/media/common/tuners/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o obj-$(CONFIG_MEDIA_TUNER_QT1010) += qt1010.o obj-$(CONFIG_MEDIA_TUNER_MT2131) += mt2131.o +obj-$(CONFIG_MEDIA_TUNER_MXL5005S) += mxl5005s.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/frontends -- cgit v1.1 From 671294719628f1671faefd4882764886f8ad08cb Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Thu, 1 May 2008 07:23:23 -0300 Subject: V4L/DVB(7879): Adding cx18 Support for mxl5005s Adding cx18 Support Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/Kconfig | 1 + drivers/media/video/cx18/cx18-cards.c | 3 ++- drivers/media/video/cx18/cx18-dvb.c | 40 +++++++++++++++++------------------ 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/media/video/cx18/Kconfig b/drivers/media/video/cx18/Kconfig index 35a5599..5f94269 100644 --- a/drivers/media/video/cx18/Kconfig +++ b/drivers/media/video/cx18/Kconfig @@ -11,6 +11,7 @@ config VIDEO_CX18 select VIDEO_CX2341X select VIDEO_CS5345 select DVB_S5H1409 + select MEDIA_TUNER_MXL5005S ---help--- This is a video4linux driver for Conexant cx23418 based PCI combo video recorder devices. diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index f5e3ba1..bf6f7ed 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -51,7 +51,8 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_muxer = CX18_HW_CS5345, - .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | CX18_HW_CS5345, + .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | CX18_HW_CS5345 + | CX18_HW_DVB, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, diff --git a/drivers/media/video/cx18/cx18-dvb.c b/drivers/media/video/cx18/cx18-dvb.c index 65efe69..c974417 100644 --- a/drivers/media/video/cx18/cx18-dvb.c +++ b/drivers/media/video/cx18/cx18-dvb.c @@ -24,25 +24,27 @@ #include "cx18-streams.h" #include "cx18-cards.h" #include "s5h1409.h" - -/* Wait until the MXL500X driver is merged */ -#ifdef HAVE_MXL500X -#include "mxl500x.h" -#endif +#include "mxl5005s.h" DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr); #define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000 -#ifdef HAVE_MXL500X -static struct mxl500x_config hauppauge_hvr1600_tuner = { - .delsys = MXL500x_MODE_ATSC, - .octf = MXL500x_OCTF_CH, - .xtal_freq = 16000000, - .iflo_freq = 5380000, - .ref_freq = 322800000, - .rssi_ena = MXL_RSSI_ENABLE, - .addr = 0xC6 >> 1, +static struct mxl5005s_config hauppauge_hvr1600_tuner = { + .i2c_address = 0xC6 >> 1, + .if_freq = IF_FREQ_5380000HZ, + .xtal_freq = CRYSTAL_FREQ_16000000HZ, + .agc_mode = MXL_SINGLE_AGC, + .tracking_filter = MXL_TF_C_H, + .rssi_enable = MXL_RSSI_ENABLE, + .cap_select = MXL_CAP_SEL_ENABLE, + .div_out = MXL_DIV_OUT_4, + .clock_out = MXL_CLOCK_OUT_DISABLE, + .output_load = MXL5005S_IF_OUTPUT_LOAD_200_OHM, + .top = MXL5005S_TOP_25P2, + .mod_mode = MXL_DIGITAL_MODE, + .if_mode = MXL_ZERO_IF, + .AgcMasterByte = 0x00, }; static struct s5h1409_config hauppauge_hvr1600_config = { @@ -55,7 +57,6 @@ static struct s5h1409_config hauppauge_hvr1600_config = { .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK }; -#endif static int dvb_register(struct cx18_stream *stream); @@ -252,21 +253,18 @@ static int dvb_register(struct cx18_stream *stream) int ret = 0; switch (cx->card->type) { -/* Wait until the MXL500X driver is merged */ -#ifdef HAVE_MXL500X case CX18_CARD_HVR_1600_ESMT: case CX18_CARD_HVR_1600_SAMSUNG: dvb->fe = dvb_attach(s5h1409_attach, &hauppauge_hvr1600_config, &cx->i2c_adap[0]); if (dvb->fe != NULL) { - dvb_attach(mxl500x_attach, dvb->fe, - &hauppauge_hvr1600_tuner, - &cx->i2c_adap[0]); + dvb_attach(mxl5005s_attach, dvb->fe, + &cx->i2c_adap[0], + &hauppauge_hvr1600_tuner); ret = 0; } break; -#endif default: /* No Digital Tv Support */ break; -- cgit v1.1 From c1d6861b5178c184d78ae5f239cbaa9c2c63dd72 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Thu, 8 May 2008 22:57:20 -0300 Subject: V4L/DVB (7880): saa7134: remove explicit GPIO initialization This causes a problem with the audio mute on some cards and is done implictly in the audio initialization code. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index eec1278..d9ad2f8 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -1065,11 +1065,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, if (TUNER_ABSENT != dev->tuner_type) saa7134_i2c_call_clients(dev, TUNER_SET_STANDBY, NULL); - if (card(dev).gpiomask != 0) { - mask = card(dev).gpiomask; - saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); - saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, 0); - } return 0; fail4: -- cgit v1.1 From 6db6ae2165863e26b7f41af54a8cf1ef9051a608 Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Mon, 12 May 2008 20:34:02 -0300 Subject: V4L/DVB (7881): saa7134: fixed a compile warning in saa7134-core.c patch 779169257208 made the variable mask unnecessary. This patch just removes the declaration. Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index d9ad2f8..2c19cd0 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -864,7 +864,6 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, struct saa7134_dev *dev; struct saa7134_mpeg_ops *mops; int err; - int mask; if (saa7134_devcount == SAA7134_MAXBOARDS) return -ENOMEM; -- cgit v1.1 From 9dcbf35afb7359466efdf7fb81ee32f3ae2d56a3 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 12 May 2008 13:57:18 -0300 Subject: V4L/DVB (7887): cx18: fix Compro H900 analog support. Tuner, S-Video and Composite are all working for the Compro H900. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-cards.c | 12 +++++---- drivers/media/video/cx18/cx18-cards.h | 5 ++-- drivers/media/video/cx18/cx18-gpio.c | 47 +++++++++++++++++++++++++++-------- 3 files changed, 46 insertions(+), 18 deletions(-) diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index bf6f7ed..0f2bfb4 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -135,14 +135,15 @@ static const struct cx18_card_pci_info cx18_pci_h900[] = { static const struct cx18_card cx18_card_h900 = { .type = CX18_CARD_COMPRO_H900, .name = "Compro VideoMate H900", - .comment = "Not yet supported!\n", - .v4l2_capabilities = 0, + .comment = "DVB & VBI are not yet supported\n", + .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_all = CX18_HW_TUNER, .video_inputs = { - { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, - { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, - { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE3 }, + { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE2 }, + { CX18_CARD_INPUT_SVIDEO1, 1, + CX23418_SVIDEO_LUMA3 | CX23418_SVIDEO_CHROMA4 }, + { CX18_CARD_INPUT_COMPOSITE1, 1, CX23418_COMPOSITE1 }, }, .audio_inputs = { { CX18_CARD_INPUT_AUD_TUNER, @@ -164,6 +165,7 @@ static const struct cx18_card cx18_card_h900 = { .tune_lane = 0, .initial_emrs = 0, }, + .xceive_pin = 15, .pci_list = cx18_pci_h900, .i2c = &cx18_i2c_std, }; diff --git a/drivers/media/video/cx18/cx18-cards.h b/drivers/media/video/cx18/cx18-cards.h index bca249b..bccb67f 100644 --- a/drivers/media/video/cx18/cx18-cards.h +++ b/drivers/media/video/cx18/cx18-cards.h @@ -114,8 +114,8 @@ struct cx18_card_pci_info { /* The mask is the set of bits used by the operation */ struct cx18_gpio_init { /* set initial GPIO DIR and OUT values */ - u16 direction; /* DIR setting. Leave to 0 if no init is needed */ - u16 initial_value; + u32 direction; /* DIR setting. Leave to 0 if no init is needed */ + u32 initial_value; }; struct cx18_card_tuner { @@ -153,6 +153,7 @@ struct cx18_card { struct cx18_card_audio_input radio_input; /* GPIO card-specific settings */ + u8 xceive_pin; /* XCeive tuner GPIO reset pin */ struct cx18_gpio_init gpio_init; struct cx18_card_tuner tuners[CX18_CARD_MAX_TUNERS]; diff --git a/drivers/media/video/cx18/cx18-gpio.c b/drivers/media/video/cx18/cx18-gpio.c index 19253e6..bb8bc86 100644 --- a/drivers/media/video/cx18/cx18-gpio.c +++ b/drivers/media/video/cx18/cx18-gpio.c @@ -35,6 +35,9 @@ #define CX18_REG_GPIO_OUT2 0xc78104 #define CX18_REG_GPIO_DIR2 0xc7810c +static u32 gpio_dir; +static u32 gpio_val; + /* * HVR-1600 GPIO pins, courtesy of Hauppauge: * @@ -44,31 +47,53 @@ * gpio13: cs5345 reset pin */ +static void gpio_write(struct cx18 *cx) +{ + write_reg((gpio_dir & 0xffff) << 16, CX18_REG_GPIO_DIR1); + write_reg(((gpio_dir & 0xffff) << 16) | (gpio_val & 0xffff), + CX18_REG_GPIO_OUT1); + write_reg(gpio_dir & 0xffff0000, CX18_REG_GPIO_DIR2); + write_reg((gpio_dir & 0xffff0000) | ((gpio_val & 0xffff0000) >> 16), + CX18_REG_GPIO_OUT2); +} + void cx18_gpio_init(struct cx18 *cx) { - if (cx->card->gpio_init.direction == 0) + gpio_dir = cx->card->gpio_init.direction; + gpio_val = cx->card->gpio_init.initial_value; + + if (gpio_dir == 0) return; - CX18_DEBUG_INFO("GPIO initial dir: %08x out: %08x\n", - read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_OUT1)); + gpio_dir |= 1 << cx->card->xceive_pin; + gpio_val |= 1 << cx->card->xceive_pin; - /* init output data then direction */ - write_reg(cx->card->gpio_init.direction << 16, CX18_REG_GPIO_DIR1); - write_reg(0, CX18_REG_GPIO_DIR2); - write_reg((cx->card->gpio_init.direction << 16) | - cx->card->gpio_init.initial_value, CX18_REG_GPIO_OUT1); - write_reg(0, CX18_REG_GPIO_OUT2); + CX18_DEBUG_INFO("GPIO initial dir: %08x/%08x out: %08x/%08x\n", + read_reg(CX18_REG_GPIO_DIR1), read_reg(CX18_REG_GPIO_DIR2), + read_reg(CX18_REG_GPIO_OUT1), read_reg(CX18_REG_GPIO_OUT2)); + + gpio_write(cx); } /* Xceive tuner reset function */ int cx18_reset_tuner_gpio(void *dev, int cmd, int value) { struct i2c_algo_bit_data *algo = dev; - struct cx18 *cx = algo->data; -/* int curdir, curout;*/ + struct cx18_i2c_algo_callback_data *cb_data = algo->data; + struct cx18 *cx = cb_data->cx; if (cmd != XC2028_TUNER_RESET) return 0; CX18_DEBUG_INFO("Resetting tuner\n"); + + gpio_dir |= 1 << cx->card->xceive_pin; + gpio_val &= ~(1 << cx->card->xceive_pin); + + gpio_write(cx); + schedule_timeout_interruptible(msecs_to_jiffies(1)); + + gpio_val |= 1 << cx->card->xceive_pin; + gpio_write(cx); + schedule_timeout_interruptible(msecs_to_jiffies(1)); return 0; } -- cgit v1.1 From 6b13cf164958a18436075fdae31f8bd9442353fa Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 12 May 2008 14:00:33 -0300 Subject: V4L/DVB (7888): cx18: minor card definition updates. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-cards.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 0f2bfb4..18489cc 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -47,12 +47,12 @@ static struct cx18_card_tuner_i2c cx18_i2c_std = { static const struct cx18_card cx18_card_hvr1600_esmt = { .type = CX18_CARD_HVR_1600_ESMT, .name = "Hauppauge HVR-1600", - .comment = "DVB & VBI are not yet supported\n", + .comment = "VBI is not yet supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_muxer = CX18_HW_CS5345, - .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | CX18_HW_CS5345 - | CX18_HW_DVB, + .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | + CX18_HW_CS5345 | CX18_HW_DVB, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, @@ -203,8 +203,6 @@ static const struct cx18_card cx18_card_mpc718 = { /* XC3028 tuner */ { .std = V4L2_STD_ALL, .tuner = TUNER_XC2028 }, }, - /* tuner reset */ - .gpio_init = { .direction = 0x1000, .initial_value = 0x1000 }, .ddr = { /* Probably Samsung K4D263238G-VC33 memory */ .chip_config = 0x003, @@ -214,6 +212,7 @@ static const struct cx18_card cx18_card_mpc718 = { .tune_lane = 0, .initial_emrs = 2, }, + .xceive_pin = 15, .pci_list = cx18_pci_mpc718, .i2c = &cx18_i2c_std, }; -- cgit v1.1 From 1d081601315f5c9b9537b702bcb2c8d96fc089ef Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 12 May 2008 14:45:19 -0300 Subject: V4L/DVB (7889): cx18: improve HVR-1600 detection. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-cards.c | 5 +++-- drivers/media/video/cx18/cx18-driver.c | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/cx18/cx18-cards.c b/drivers/media/video/cx18/cx18-cards.c index 18489cc..553adbf 100644 --- a/drivers/media/video/cx18/cx18-cards.c +++ b/drivers/media/video/cx18/cx18-cards.c @@ -87,11 +87,12 @@ static const struct cx18_card cx18_card_hvr1600_esmt = { static const struct cx18_card cx18_card_hvr1600_samsung = { .type = CX18_CARD_HVR_1600_SAMSUNG, .name = "Hauppauge HVR-1600 (Preproduction)", - .comment = "DVB & VBI are not yet supported\n", + .comment = "VBI is not yet supported\n", .v4l2_capabilities = CX18_CAP_ENCODER, .hw_audio_ctrl = CX18_HW_CX23418, .hw_muxer = CX18_HW_CS5345, - .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | CX18_HW_CS5345, + .hw_all = CX18_HW_TVEEPROM | CX18_HW_TUNER | + CX18_HW_CS5345 | CX18_HW_DVB, .video_inputs = { { CX18_CARD_INPUT_VID_TUNER, 0, CX23418_COMPOSITE7 }, { CX18_CARD_INPUT_SVIDEO1, 1, CX23418_SVIDEO1 }, diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 3e9979e..98e1bdd 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -210,13 +210,13 @@ static void cx18_process_eeprom(struct cx18 *cx) /* Many thanks to Steven Toth from Hauppauge for providing the model numbers */ + /* Note: the Samsung memory models cannot be reliably determined + from the model number. Use the cardtype module option if you + have one of these preproduction models. */ switch (tv.model) { - case 74000 ... 74099: + case 74000 ... 74999: cx->card = cx18_get_card(CX18_CARD_HVR_1600_ESMT); break; - case 74700 ... 74799: - cx->card = cx18_get_card(CX18_CARD_HVR_1600_SAMSUNG); - break; case 0: CX18_ERR("Invalid EEPROM\n"); return; -- cgit v1.1 From cba627a51a26eaed3526c423f5fd0410dd721ae2 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 12 May 2008 14:48:26 -0300 Subject: V4L/DVB (7890): cx18: removed bogus and confusing conditional Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-driver.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/video/cx18/cx18-driver.c b/drivers/media/video/cx18/cx18-driver.c index 98e1bdd..0dd4e05 100644 --- a/drivers/media/video/cx18/cx18-driver.c +++ b/drivers/media/video/cx18/cx18-driver.c @@ -904,8 +904,7 @@ static void cx18_remove(struct pci_dev *pci_dev) free_irq(cx->dev->irq, (void *)cx); - if (cx->dev) - cx18_iounmap(cx); + cx18_iounmap(cx); release_mem_region(cx->base_addr, CX18_MEM_SIZE); -- cgit v1.1 From 07c87a833e9ef92280ed24ab85cd4eb49cbca9c0 Mon Sep 17 00:00:00 2001 From: Andy Walls Date: Mon, 12 May 2008 15:01:27 -0300 Subject: V4L/DVB (7891): cx18/ivtv: fix open() kernel oops Upon error conditions in cx18/ivtv_probe(), the code at the 'err:' label leaves a NULL entry in cx18/ivtv_cards[]. This can cause a NULL pointer de-reference in cx18/ivtv_v4l2_open() which is fixed by this patch. Signed-off-by: Andy Walls Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx18/cx18-fileops.c | 2 ++ drivers/media/video/ivtv/ivtv-fileops.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c index 91eff6e..0b3141d 100644 --- a/drivers/media/video/cx18/cx18-fileops.c +++ b/drivers/media/video/cx18/cx18-fileops.c @@ -662,6 +662,8 @@ int cx18_v4l2_open(struct inode *inode, struct file *filp) for (x = 0; cx == NULL && x < cx18_cards_active; x++) { /* find out which stream this open was on */ for (y = 0; y < CX18_MAX_STREAMS; y++) { + if (cx18_cards[x] == NULL) + continue; s = &cx18_cards[x]->streams[y]; if (s->v4l2dev && s->v4l2dev->minor == minor) { cx = cx18_cards[x]; diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 2b74b0a..f2fa434 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -987,6 +987,8 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) /* Find which card this open was on */ spin_lock(&ivtv_cards_lock); for (x = 0; itv == NULL && x < ivtv_cards_active; x++) { + if (ivtv_cards[x] == NULL) + continue; /* find out which stream this open was on */ for (y = 0; y < IVTV_MAX_STREAMS; y++) { s = &ivtv_cards[x]->streams[y]; -- cgit v1.1 From 48723543aff1f46091840222490ded5fe09c0e37 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sat, 10 May 2008 14:34:09 -0300 Subject: V4L/DVB (7893): xc5000: bug-fix: allow multiple devices in a single system The current code passes a context pointer in the xc5000_config struct. This context pointer is used in the tuner_callback function, used to reset the device after firmware download. The xc5000_config struct is a static structure, whose .priv member was being assigned before calling xc5000_attach(). If there are more than one of the same device type installed on a single system, the last one to assign xc5000_config.priv will "win", and all others will cease to function properly. This patch passes the context pointer in xc5000_attach() rather that storing it within the static struct xc5000_config. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/xc5000.c | 9 +++++---- drivers/media/common/tuners/xc5000.h | 22 ++++++++++++---------- drivers/media/common/tuners/xc5000_priv.h | 2 ++ drivers/media/video/au0828/au0828-dvb.c | 6 ++---- drivers/media/video/cx23885/cx23885-dvb.c | 6 ++---- drivers/media/video/cx88/cx88-dvb.c | 10 ++++------ drivers/media/video/tuner-core.c | 4 ++-- 7 files changed, 29 insertions(+), 30 deletions(-) diff --git a/drivers/media/common/tuners/xc5000.c b/drivers/media/common/tuners/xc5000.c index 43d35bd..ceae6db 100644 --- a/drivers/media/common/tuners/xc5000.c +++ b/drivers/media/common/tuners/xc5000.c @@ -212,7 +212,7 @@ static void xc5000_TunerReset(struct dvb_frontend *fe) dprintk(1, "%s()\n", __func__); if (priv->cfg->tuner_callback) { - ret = priv->cfg->tuner_callback(priv->cfg->priv, + ret = priv->cfg->tuner_callback(priv->devptr, XC5000_TUNER_RESET, 0); if (ret) printk(KERN_ERR "xc5000: reset failed\n"); @@ -900,9 +900,9 @@ static const struct dvb_tuner_ops xc5000_tuner_ops = { .get_status = xc5000_get_status }; -struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe, - struct i2c_adapter *i2c, - struct xc5000_config *cfg) +struct dvb_frontend *xc5000_attach(struct dvb_frontend *fe, + struct i2c_adapter *i2c, + struct xc5000_config *cfg, void *devptr) { struct xc5000_priv *priv = NULL; u16 id = 0; @@ -916,6 +916,7 @@ struct dvb_frontend * xc5000_attach(struct dvb_frontend *fe, priv->cfg = cfg; priv->bandwidth = BANDWIDTH_6_MHZ; priv->i2c = i2c; + priv->devptr = devptr; /* Check if firmware has been loaded. It is possible that another instance of the driver has loaded the firmware. diff --git a/drivers/media/common/tuners/xc5000.h b/drivers/media/common/tuners/xc5000.h index 0ee80f9..c910715 100644 --- a/drivers/media/common/tuners/xc5000.h +++ b/drivers/media/common/tuners/xc5000.h @@ -31,29 +31,31 @@ struct xc5000_config { u8 i2c_address; u32 if_khz; - /* For each bridge framework, when it attaches either analog or digital, - * it has to store a reference back to its _core equivalent structure, - * so that it can service the hardware by steering gpio's etc. - * Each bridge implementation is different so cast priv accordingly. - * The xc5000 driver cares not for this value, other than ensuring - * it's passed back to a bridge during tuner_callback(). - */ - void *priv; int (*tuner_callback) (void *priv, int command, int arg); }; /* xc5000 callback command */ #define XC5000_TUNER_RESET 0 +/* For each bridge framework, when it attaches either analog or digital, + * it has to store a reference back to its _core equivalent structure, + * so that it can service the hardware by steering gpio's etc. + * Each bridge implementation is different so cast devptr accordingly. + * The xc5000 driver cares not for this value, other than ensuring + * it's passed back to a bridge during tuner_callback(). + */ + #if defined(CONFIG_MEDIA_TUNER_XC5000) || \ (defined(CONFIG_MEDIA_TUNER_XC5000_MODULE) && defined(MODULE)) extern struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, - struct xc5000_config *cfg); + struct xc5000_config *cfg, + void *devptr); #else static inline struct dvb_frontend* xc5000_attach(struct dvb_frontend *fe, struct i2c_adapter *i2c, - struct xc5000_config *cfg) + struct xc5000_config *cfg, + void *devptr) { printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__); return NULL; diff --git a/drivers/media/common/tuners/xc5000_priv.h b/drivers/media/common/tuners/xc5000_priv.h index 13b2d19..ecebfe4 100644 --- a/drivers/media/common/tuners/xc5000_priv.h +++ b/drivers/media/common/tuners/xc5000_priv.h @@ -31,6 +31,8 @@ struct xc5000_priv { u8 video_standard; u8 rf_mode; u8 fwloaded; + + void *devptr; }; #endif diff --git a/drivers/media/video/au0828/au0828-dvb.c b/drivers/media/video/au0828/au0828-dvb.c index 1371b4e..c86a5f1 100644 --- a/drivers/media/video/au0828/au0828-dvb.c +++ b/drivers/media/video/au0828/au0828-dvb.c @@ -337,12 +337,10 @@ int au0828_dvb_register(struct au0828_dev *dev) dvb->frontend = dvb_attach(au8522_attach, &hauppauge_hvr950q_config, &dev->i2c_adap); - if (dvb->frontend != NULL) { - hauppauge_hvr950q_tunerconfig.priv = dev; + if (dvb->frontend != NULL) dvb_attach(xc5000_attach, dvb->frontend, &dev->i2c_adap, - &hauppauge_hvr950q_tunerconfig); - } + &hauppauge_hvr950q_tunerconfig, dev); break; default: printk(KERN_WARNING "The frontend of your DVB/ATSC card " diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 47e3f9e..022aa39 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -384,12 +384,10 @@ static int dvb_register(struct cx23885_tsport *port) port->dvb.frontend = dvb_attach(s5h1409_attach, &hauppauge_hvr1500q_config, &dev->i2c_bus[0].i2c_adap); - if (port->dvb.frontend != NULL) { - hauppauge_hvr1500q_tunerconfig.priv = i2c_bus; + if (port->dvb.frontend != NULL) dvb_attach(xc5000_attach, port->dvb.frontend, &i2c_bus->i2c_adap, - &hauppauge_hvr1500q_tunerconfig); - } + &hauppauge_hvr1500q_tunerconfig, i2c_bus); break; case CX23885_BOARD_HAUPPAUGE_HVR1500: i2c_bus = &dev->i2c_bus[1]; diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 75e2e58..d96173f 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -816,11 +816,10 @@ static int dvb_register(struct cx8802_dev *dev) /* tuner_config.video_dev must point to * i2c_adap.algo_data */ - pinnacle_pctv_hd_800i_tuner_config.priv = - core->i2c_adap.algo_data; if (!dvb_attach(xc5000_attach, dev->dvb.frontend, &core->i2c_adap, - &pinnacle_pctv_hd_800i_tuner_config)) + &pinnacle_pctv_hd_800i_tuner_config, + core->i2c_adap.algo_data)) goto frontend_detach; } break; @@ -878,11 +877,10 @@ static int dvb_register(struct cx8802_dev *dev) /* tuner_config.video_dev must point to * i2c_adap.algo_data */ - dvico_fusionhdtv7_tuner_config.priv = - core->i2c_adap.algo_data; if (!dvb_attach(xc5000_attach, dev->dvb.frontend, &core->i2c_adap, - &dvico_fusionhdtv7_tuner_config)) + &dvico_fusionhdtv7_tuner_config, + core->i2c_adap.algo_data)) goto frontend_detach; } break; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 4ca686f..5a75788 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -448,10 +448,10 @@ static void set_type(struct i2c_client *c, unsigned int type, xc5000_cfg.i2c_address = t->i2c->addr; xc5000_cfg.if_khz = 5380; - xc5000_cfg.priv = c->adapter->algo_data; xc5000_cfg.tuner_callback = t->tuner_callback; if (!dvb_attach(xc5000_attach, - &t->fe, t->i2c->adapter, &xc5000_cfg)) + &t->fe, t->i2c->adapter, &xc5000_cfg, + c->adapter->algo_data)) goto attach_failed; xc_tuner_ops = &t->fe.ops.tuner_ops; -- cgit v1.1 From ee04e0faad386141f52dd812f220a2f0d128f1c6 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 13 May 2008 01:25:24 -0300 Subject: V4L/DVB (7895): tveeprom: update Hauppauge analog audio and video decoders Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tveeprom.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 3cf8a8e..9da0e18 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -319,10 +319,12 @@ audioIC[] = {AUDIO_CHIP_INTERNAL, "CX25843"}, {AUDIO_CHIP_INTERNAL, "CX23418"}, {AUDIO_CHIP_INTERNAL, "CX23885"}, - /* 40-42 */ + /* 40-44 */ {AUDIO_CHIP_INTERNAL, "CX23888"}, {AUDIO_CHIP_INTERNAL, "SAA7131"}, {AUDIO_CHIP_INTERNAL, "CX23887"}, + {AUDIO_CHIP_INTERNAL, "SAA7164"}, + {AUDIO_CHIP_INTERNAL, "AU8522"}, }; /* This list is supplied by Hauppauge. Thanks! */ @@ -341,8 +343,10 @@ static const char *decoderIC[] = { "CX882", "TVP5150A", "CX25840", "CX25841", "CX25842", /* 30-34 */ "CX25843", "CX23418", "NEC61153", "CX23885", "CX23888", - /* 35-37 */ - "SAA7131", "CX25837", "CX23887" + /* 35-39 */ + "SAA7131", "CX25837", "CX23887", "CX23885A", "CX23887A", + /* 40-42 */ + "SAA7164", "CX23885B", "AU8522" }; static int hasRadioTuner(int tunerType) -- cgit v1.1 From 039d40019f3c5e26ea50ec5af4270189f63365e1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 14 May 2008 04:36:22 -0300 Subject: V4L/DVB (7898): Fix VIDEO_MEDIA Kconfig logic If one of DVB_CORE or VIDEO_DEV is a module, the modules that can be used by both DVB and V4L cores should also be a module, otherwise, it will break its dependencies. This Kconfig logic implements the following: CONFIG_VIDEO_DEV CONFIG_DVB_CORE CONFIG_VIDEO_MEDIA N N N N M M N Y Y M N M M M M M Y M Y N Y Y M M Y Y Y Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index ddf57e13..7a7803b 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -89,8 +89,7 @@ config DVB_CORE config VIDEO_MEDIA tristate - default DVB_CORE || VIDEO_DEV - depends on DVB_CORE || VIDEO_DEV + default (DVB_CORE && (VIDEO_DEV = n)) || (VIDEO_DEV && (DVB_CORE = n)) || (DVB_CORE && VIDEO_DEV) comment "Multimedia drivers" -- cgit v1.1 From 2ea336dc117098ef917ca9a19e911d15490587cc Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 14 May 2008 04:57:36 -0300 Subject: V4L/DVB (7899): Fixes a few remaining Kbuild issues at common/tuners - MEDIA_ATTACH now applies also for V4L; - select a FW_LOADER dependent driver should happen only if HOTPLUG; - apply the common tuner dependency to all tuners. This helps to avoid latter issues. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/common/tuners/Kconfig | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/media/common/tuners/Kconfig b/drivers/media/common/tuners/Kconfig index 394cb05..d620654 100644 --- a/drivers/media/common/tuners/Kconfig +++ b/drivers/media/common/tuners/Kconfig @@ -1,6 +1,6 @@ config MEDIA_ATTACH bool "Load and attach frontend and tuner driver modules as needed" - depends on DVB_CORE + depends on VIDEO_MEDIA depends on MODULES help Remove the static dependency of DVB card drivers on all @@ -22,7 +22,7 @@ config MEDIA_TUNER default VIDEO_MEDIA && I2C depends on VIDEO_MEDIA && I2C select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG - select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE + select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMIZE && HOTPLUG select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMIZE select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMIZE @@ -46,6 +46,7 @@ if MEDIA_TUNER_CUSTOMIZE config MEDIA_TUNER_SIMPLE tristate "Simple tuner support" + depends on VIDEO_MEDIA && I2C select MEDIA_TUNER_TDA9887 default m if MEDIA_TUNER_CUSTOMIZE help @@ -53,6 +54,7 @@ config MEDIA_TUNER_SIMPLE config MEDIA_TUNER_TDA8290 tristate "TDA 8290/8295 + 8275(a)/18271 tuner combo" + depends on VIDEO_MEDIA && I2C select MEDIA_TUNER_TDA827X select MEDIA_TUNER_TDA18271 default m if MEDIA_TUNER_CUSTOMIZE @@ -61,18 +63,21 @@ config MEDIA_TUNER_TDA8290 config MEDIA_TUNER_TDA827X tristate "Philips TDA827X silicon tuner" + depends on VIDEO_MEDIA && I2C default m if DVB_FE_CUSTOMISE help A DVB-T silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA18271 tristate "NXP TDA18271 silicon tuner" + depends on VIDEO_MEDIA && I2C default m if DVB_FE_CUSTOMISE help A silicon tuner module. Say Y when you want to support this tuner. config MEDIA_TUNER_TDA9887 tristate "TDA 9885/6/7 analog IF demodulator" + depends on VIDEO_MEDIA && I2C default m if MEDIA_TUNER_CUSTOMIZE help Say Y here to include support for Philips TDA9885/6/7 @@ -80,6 +85,7 @@ config MEDIA_TUNER_TDA9887 config MEDIA_TUNER_TEA5761 tristate "TEA 5761 radio tuner (EXPERIMENTAL)" + depends on VIDEO_MEDIA && I2C depends on EXPERIMENTAL default m if MEDIA_TUNER_CUSTOMIZE help @@ -87,42 +93,49 @@ config MEDIA_TUNER_TEA5761 config MEDIA_TUNER_TEA5767 tristate "TEA 5767 radio tuner" + depends on VIDEO_MEDIA && I2C default m if MEDIA_TUNER_CUSTOMIZE help Say Y here to include support for the Philips TEA5767 radio tuner. config MEDIA_TUNER_MT20XX tristate "Microtune 2032 / 2050 tuners" + depends on VIDEO_MEDIA && I2C default m if MEDIA_TUNER_CUSTOMIZE help Say Y here to include support for the MT2032 / MT2050 tuner. config MEDIA_TUNER_MT2060 tristate "Microtune MT2060 silicon IF tuner" + depends on VIDEO_MEDIA && I2C default m if DVB_FE_CUSTOMISE help A driver for the silicon IF tuner MT2060 from Microtune. config MEDIA_TUNER_MT2266 tristate "Microtune MT2266 silicon tuner" + depends on VIDEO_MEDIA && I2C default m if DVB_FE_CUSTOMISE help A driver for the silicon baseband tuner MT2266 from Microtune. config MEDIA_TUNER_MT2131 tristate "Microtune MT2131 silicon tuner" + depends on VIDEO_MEDIA && I2C default m if DVB_FE_CUSTOMISE help A driver for the silicon baseband tuner MT2131 from Microtune. config MEDIA_TUNER_QT1010 tristate "Quantek QT1010 silicon tuner" + depends on VIDEO_MEDIA && I2C default m if DVB_FE_CUSTOMISE help A driver for the silicon tuner QT1010 from Quantek. config MEDIA_TUNER_XC2028 tristate "XCeive xc2028/xc3028 tuners" + depends on VIDEO_MEDIA && I2C depends on HOTPLUG select FW_LOADER default m if MEDIA_TUNER_CUSTOMIZE @@ -131,6 +144,7 @@ config MEDIA_TUNER_XC2028 config MEDIA_TUNER_XC5000 tristate "Xceive XC5000 silicon tuner" + depends on VIDEO_MEDIA && I2C depends on HOTPLUG select FW_LOADER default m if DVB_FE_CUSTOMISE @@ -141,7 +155,7 @@ config MEDIA_TUNER_XC5000 config MEDIA_TUNER_MXL5005S tristate "MaxLinear MSL5005S silicon tuner" - depends on I2C + depends on VIDEO_MEDIA && I2C default m if DVB_FE_CUSTOMISE help A driver for the silicon tuner MXL5005S from MaxLinear. -- cgit v1.1 From c2b7bbea83b239b1877f3cafe0cdcbbd08e65648 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 14 May 2008 05:08:19 -0300 Subject: V4L/DVB (7900): pvrusb: Fix Kconfig if DVB=m V4L_core=y As reported by Ingo Molnar: x86.git testing found the following build failure: drivers/built-in.o: In function `pvr2_dvb_feed_thread': pvrusb2-dvb.c:(.text+0x127e78): undefined reference to `dvb_dmx_swfilter' drivers/built-in.o: In function `pvr2_dvb_adapter_exit': pvrusb2-dvb.c:(.text+0x128357): undefined reference to `dvb_net_release' pvrusb2-dvb.c:(.text+0x12836f): undefined reference to `dvb_dmxdev_release' [...] with this config: CONFIG_VIDEO_PVRUSB2=y CONFIG_DVB_CORE=m i.e. pvrusb2 is built-in, dvb-core is modular. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pvrusb2/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/pvrusb2/Kconfig b/drivers/media/video/pvrusb2/Kconfig index e2a7a50..4482b2c 100644 --- a/drivers/media/video/pvrusb2/Kconfig +++ b/drivers/media/video/pvrusb2/Kconfig @@ -1,6 +1,7 @@ config VIDEO_PVRUSB2 tristate "Hauppauge WinTV-PVR USB2 support" depends on VIDEO_V4L2 && I2C + depends on VIDEO_MEDIA # Avoids pvrusb = Y / DVB = M depends on HOTPLUG # due to FW_LOADER select FW_LOADER select VIDEO_TUNER -- cgit v1.1 From 5e0f8923f350ff522f8f6aecf198df045af3615f Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 13 May 2008 23:23:55 -0700 Subject: cipso: Relax too much careful cipso hash function. The cipso_v4_cache is allocated to contain CIPSO_V4_CACHE_BUCKETS buckets. The CIPSO_V4_CACHE_BUCKETS = 1 << CIPSO_V4_CACHE_BUCKETBITS, where CIPSO_V4_CACHE_BUCKETBITS = 7. The bucket-selection function for this hash is calculated like this: bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); ^^^ i.e. picking only 4 buckets of possible 128 :) Signed-off-by: Pavel Emelyanov Acked-by: Paul Moore Signed-off-by: David S. Miller --- net/ipv4/cipso_ipv4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 05afb57..2c0e457 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c @@ -338,7 +338,7 @@ static int cipso_v4_cache_check(const unsigned char *key, return -ENOENT; hash = cipso_v4_map_cache_hash(key, key_len); - bkt = hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); + bkt = hash & (CIPSO_V4_CACHE_BUCKETS - 1); spin_lock_bh(&cipso_v4_cache[bkt].lock); list_for_each_entry(entry, &cipso_v4_cache[bkt].list, list) { if (entry->hash == hash && @@ -417,7 +417,7 @@ int cipso_v4_cache_add(const struct sk_buff *skb, atomic_inc(&secattr->cache->refcount); entry->lsm_data = secattr->cache; - bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETBITS - 1); + bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETS - 1); spin_lock_bh(&cipso_v4_cache[bkt].lock); if (cipso_v4_cache[bkt].size < cipso_v4_cache_bucketsize) { list_add(&entry->list, &cipso_v4_cache[bkt].list); -- cgit v1.1 From c1cc678adaa78ae2aab6a6d699241ad516d84476 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 13 May 2008 23:25:00 -0700 Subject: sctp: Fix use of uninitialized pointer Introduced by c4492586 (sctp: Add address type check while process paramaters of ASCONF chunk): net/sctp/sm_make_chunk.c: In function 'sctp_process_asconf': net/sctp/sm_make_chunk.c:2828: warning: 'addr_param' may be used uninitialized in this function net/sctp/sm_make_chunk.c:2828: note: 'addr_param' was declared here Signed-off-by: Patrick McHardy Acked-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/sm_make_chunk.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 6eeee53..bbc7107 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c @@ -2827,6 +2827,9 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, union sctp_addr addr; union sctp_addr_param *addr_param; + addr_param = (union sctp_addr_param *) + ((void *)asconf_param + sizeof(sctp_addip_param_t)); + switch (addr_param->v4.param_hdr.type) { case SCTP_PARAM_IPV6_ADDRESS: if (!asoc->peer.ipv6_address) @@ -2840,9 +2843,6 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, return SCTP_ERROR_INV_PARAM; } - addr_param = (union sctp_addr_param *) - ((void *)asconf_param + sizeof(sctp_addip_param_t)); - af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type)); if (unlikely(!af)) return SCTP_ERROR_INV_PARAM; -- cgit v1.1 From 332223831e86b2e17b48b4afafad07d8e3b73861 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Tue, 13 May 2008 23:25:57 -0700 Subject: irda: Fix a misalign access issue. (v2) Replace u16ho with put/get_unaligned functions Signed-off-by: Graf Yang Signed-off-by: Bryan Wu Signed-off-by: David S. Miller --- include/net/irda/discovery.h | 3 --- net/irda/discovery.c | 8 +++++--- net/irda/irlmp.c | 5 +++-- net/irda/irnet/irnet_irda.c | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/net/irda/discovery.h b/include/net/irda/discovery.h index e4efad1..0ce9339 100644 --- a/include/net/irda/discovery.h +++ b/include/net/irda/discovery.h @@ -57,9 +57,6 @@ typedef union { __u8 byte[2]; } __u16_host_order; -/* Same purpose, different application */ -#define u16ho(array) (* ((__u16 *) array)) - /* Types of discovery */ typedef enum { DISCOVERY_LOG, /* What's in our discovery log */ diff --git a/net/irda/discovery.c b/net/irda/discovery.c index bfacef8..a6f99b5 100644 --- a/net/irda/discovery.c +++ b/net/irda/discovery.c @@ -40,6 +40,8 @@ #include +#include + /* * Function irlmp_add_discovery (cachelog, discovery) * @@ -87,7 +89,7 @@ void irlmp_add_discovery(hashbin_t *cachelog, discovery_t *new) */ hashbin_remove_this(cachelog, (irda_queue_t *) node); /* Check if hints bits are unchanged */ - if(u16ho(node->data.hints) == u16ho(new->data.hints)) + if (get_unaligned((__u16 *)node->data.hints) == get_unaligned((__u16 *)new->data.hints)) /* Set time of first discovery for this node */ new->firststamp = node->firststamp; kfree(node); @@ -281,9 +283,9 @@ struct irda_device_info *irlmp_copy_discoveries(hashbin_t *log, int *pn, /* Mask out the ones we don't want : * We want to match the discovery mask, and to get only * the most recent one (unless we want old ones) */ - if ((u16ho(discovery->data.hints) & mask) && + if ((get_unaligned((__u16 *)discovery->data.hints) & mask) && ((old_entries) || - ((jiffies - discovery->firststamp) < j_timeout)) ) { + ((jiffies - discovery->firststamp) < j_timeout))) { /* Create buffer as needed. * As this function get called a lot and most time * we don't have anything to put in the log (we are diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c index 1f81f8e..7bf5b91 100644 --- a/net/irda/irlmp.c +++ b/net/irda/irlmp.c @@ -1062,7 +1062,8 @@ void irlmp_discovery_expiry(discinfo_t *expiries, int number) for(i = 0; i < number; i++) { /* Check if we should notify client */ if ((client->expir_callback) && - (client->hint_mask.word & u16ho(expiries[i].hints) + (client->hint_mask.word & + get_unaligned((__u16 *)expiries[i].hints) & 0x7f7f) ) client->expir_callback(&(expiries[i]), EXPIRY_TIMEOUT, @@ -1086,7 +1087,7 @@ discovery_t *irlmp_get_discovery_response(void) IRDA_ASSERT(irlmp != NULL, return NULL;); - u16ho(irlmp->discovery_rsp.data.hints) = irlmp->hints.word; + put_unaligned(irlmp->hints.word, (__u16 *)irlmp->discovery_rsp.data.hints); /* * Set character set for device name (we use ASCII), and diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c index 75497e5..a3ec002 100644 --- a/net/irda/irnet/irnet_irda.c +++ b/net/irda/irnet/irnet_irda.c @@ -1673,7 +1673,7 @@ irnet_discovery_indication(discinfo_t * discovery, /* Notify the control channel */ irnet_post_event(NULL, IRNET_DISCOVER, discovery->saddr, discovery->daddr, discovery->info, - u16ho(discovery->hints)); + get_unaligned((__u16 *)discovery->hints)); DEXIT(IRDA_OCB_TRACE, "\n"); } @@ -1704,7 +1704,7 @@ irnet_expiry_indication(discinfo_t * expiry, /* Notify the control channel */ irnet_post_event(NULL, IRNET_EXPIRE, expiry->saddr, expiry->daddr, expiry->info, - u16ho(expiry->hints)); + get_unaligned((__u16 *)expiry->hints)); DEXIT(IRDA_OCB_TRACE, "\n"); } -- cgit v1.1 From 1eedf69993d4016428fd99ffd619e73b374be3c1 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Tue, 13 May 2008 23:27:11 -0700 Subject: netfilter: ctnetlink: dump conntrack ID in event messages Conntrack ID is not put (anymore ?) in event messages. This causes current ulogd2 code to fail because it uses the ID to build a hash in userspace. This hash is used to be able to output the starting time of a connection. Conntrack ID can be used in userspace application to maintain an easy match between kernel connections list and userspace one. It may worth to add it if there is no performance related issue. [ Patrick: it was never included in events, but really should be ] Signed-off-by: Eric Leblond Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_netlink.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 16774ec..0edefcf 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c @@ -472,6 +472,9 @@ static int ctnetlink_conntrack_event(struct notifier_block *this, goto nla_put_failure; nla_nest_end(skb, nest_parms); + if (ctnetlink_dump_id(skb, ct) < 0) + goto nla_put_failure; + if (events & IPCT_DESTROY) { if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0) -- cgit v1.1 From 01b7a314291b2ef56ad718ee1374a1bac4768b29 Mon Sep 17 00:00:00 2001 From: Phil Oester Date: Tue, 13 May 2008 23:27:48 -0700 Subject: netfilter: xt_iprange: module aliases for xt_iprange Using iptables 1.3.8 with kernel 2.6.25, rules which include '-m iprange' don't automatically pull in xt_iprange module. Below patch adds module aliases to fix that. Patch against latest -git, but seems like a good candidate for -stable also. Signed-off-by: Phil Oester Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/xt_iprange.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/netfilter/xt_iprange.c b/net/netfilter/xt_iprange.c index 500528d..c63e933 100644 --- a/net/netfilter/xt_iprange.c +++ b/net/netfilter/xt_iprange.c @@ -179,3 +179,5 @@ module_exit(iprange_mt_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Jozsef Kadlecsik , Jan Engelhardt "); MODULE_DESCRIPTION("Xtables: arbitrary IPv4 range matching"); +MODULE_ALIAS("ipt_iprange"); +MODULE_ALIAS("ip6t_iprange"); -- cgit v1.1 From 4b95ede6f6116ae1c0ed9605ec97d856c4814569 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Tue, 13 May 2008 23:51:18 -0700 Subject: ppp: Do not free not yet unregistered net device. An error path in ppp_create_interface() lacks one and may BUG in free_netdev() checking for proper dev->reg_state. Signed-off-by: Pavel Emelyanov Signed-off-by: David S. Miller --- drivers/net/ppp_generic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index d3207c0..1f4ca2b 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -2458,6 +2458,7 @@ ppp_create_interface(int unit, int *retp) out3: atomic_dec(&ppp_unit_count); + unregister_netdev(dev); out2: mutex_unlock(&all_ppp_mutex); free_netdev(dev); -- cgit v1.1 From 9ee6b7f1556e7889eff4666483b1b554d4686cd4 Mon Sep 17 00:00:00 2001 From: Rami Rosen Date: Wed, 14 May 2008 03:50:03 -0700 Subject: net: Fix typo in net/core/sock.c. In sock_queue_rcv_skb() (net/core/sock.c) it should be: "Cast sk->rcvbuf ..." instead of: "Cast skb->rcvbuf ..." Signed-off-by: Rami Rosen Signed-off-by: David S. Miller --- net/core/sock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/sock.c b/net/core/sock.c index fa76f04..88094cb 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -270,7 +270,7 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) int err = 0; int skb_len; - /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces + /* Cast sk->rcvbuf to unsigned... It's pointless, but reduces number of warnings when compiling with -W --ANK */ if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= -- cgit v1.1 From 6986a978eec70c867717fe6bee736f0bd1db1508 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 2 May 2008 12:02:20 -0700 Subject: USB: add new moto_modem driver for some Morotola phones This should work on a KRZR K1m, and some other Motorola phones that do not use the "standard" cdc ACM protocol to talk to USB hosts. Tested-by: Jeff Garzik Cc: Jiang Dejun Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 9 ++++++ drivers/usb/serial/Makefile | 1 + drivers/usb/serial/moto_modem.c | 70 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 drivers/usb/serial/moto_modem.c diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 2cffec8..9ba64cc 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -447,6 +447,15 @@ config USB_SERIAL_MOS7840 To compile this driver as a module, choose M here: the module will be called mos7840. If unsure, choose N. +config USB_SERIAL_MOTOROLA + tristate "USB Motorola Phone modem driver" + ---help--- + Say Y here if you want to use a Motorola phone with a USB + connector as a modem link. + + To compile this driver as a module, choose M here: the + module will be called moto_modem. If unsure, choose N. + config USB_SERIAL_NAVMAN tristate "USB Navman GPS device" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 7568595..17a762a 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -39,6 +39,7 @@ obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o obj-$(CONFIG_USB_SERIAL_MOS7720) += mos7720.o obj-$(CONFIG_USB_SERIAL_MOS7840) += mos7840.o +obj-$(CONFIG_USB_SERIAL_MOTOROLA) += moto_modem.o obj-$(CONFIG_USB_SERIAL_NAVMAN) += navman.o obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.o obj-$(CONFIG_USB_SERIAL_OPTION) += option.o diff --git a/drivers/usb/serial/moto_modem.c b/drivers/usb/serial/moto_modem.c new file mode 100644 index 0000000..2e8e0546 --- /dev/null +++ b/drivers/usb/serial/moto_modem.c @@ -0,0 +1,70 @@ +/* + * Motorola USB Phone driver + * + * Copyright (C) 2008 Greg Kroah-Hartman + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * {sigh} + * Mororola should be using the CDC ACM USB spec, but instead + * they try to just "do their own thing"... This driver should handle a + * few phones in which a basic "dumb serial connection" is needed to be + * able to get a connection through to them. + */ + +#include +#include +#include +#include +#include +#include + +static struct usb_device_id id_table [] = { + { USB_DEVICE(0x05c6, 0x3197) }, /* unknown Motorola phone */ + { USB_DEVICE(0x0c44, 0x0022) }, /* unknown Mororola phone */ + { USB_DEVICE(0x22b8, 0x2a64) }, /* Motorola KRZR K1m */ + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_driver moto_driver = { + .name = "moto-modem", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .no_dynamic_id = 1, +}; + +static struct usb_serial_driver moto_device = { + .driver = { + .owner = THIS_MODULE, + .name = "moto-modem", + }, + .id_table = id_table, + .num_ports = 1, +}; + +static int __init moto_init(void) +{ + int retval; + + retval = usb_serial_register(&moto_device); + if (retval) + return retval; + retval = usb_register(&moto_driver); + if (retval) + usb_serial_deregister(&moto_device); + return retval; +} + +static void __exit moto_exit(void) +{ + usb_deregister(&moto_driver); + usb_serial_deregister(&moto_device); +} + +module_init(moto_init); +module_exit(moto_exit); +MODULE_LICENSE("GPL"); -- cgit v1.1 From 2e5f10e4f0a9649186d8a8c793822b2e0dae8373 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 30 Apr 2008 15:37:19 -0400 Subject: USB: create attributes before sending uevent This patch (as1087d) fixes a long-standing problem in usbcore: Device, interface, and endpoint attributes aren't added until _after_ the creation uevent has already been broadcast. Unfortunately there are a few attributes which cannot be created that early. The "descriptors" attribute is binary and so must be created separately. The power-management attributes can't be created until the dev/power/ group exists. And the interface string can vary from one altsetting to another, so it has to be created dynamically. Signed-off-by: Alan Stern Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/endpoint.c | 11 ++-- drivers/usb/core/message.c | 1 + drivers/usb/core/sysfs.c | 137 +++++++++++++++++++++++++++----------------- drivers/usb/core/usb.c | 1 + drivers/usb/core/usb.h | 4 ++ 5 files changed, 96 insertions(+), 58 deletions(-) diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index 99e5a68..fae55a3 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -156,6 +156,10 @@ static struct attribute *ep_dev_attrs[] = { static struct attribute_group ep_dev_attr_grp = { .attrs = ep_dev_attrs, }; +static struct attribute_group *ep_dev_groups[] = { + &ep_dev_attr_grp, + NULL +}; static int usb_endpoint_major_init(void) { @@ -298,6 +302,7 @@ int usb_create_ep_files(struct device *parent, ep_dev->desc = &endpoint->desc; ep_dev->udev = udev; + ep_dev->dev.groups = ep_dev_groups; ep_dev->dev.devt = MKDEV(usb_endpoint_major, ep_dev->minor); ep_dev->dev.class = ep_class->class; ep_dev->dev.parent = parent; @@ -309,9 +314,6 @@ int usb_create_ep_files(struct device *parent, retval = device_register(&ep_dev->dev); if (retval) goto error_chrdev; - retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); - if (retval) - goto error_group; /* create the symlink to the old-style "ep_XX" directory */ sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); @@ -322,8 +324,6 @@ int usb_create_ep_files(struct device *parent, return retval; error_link: - sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); -error_group: device_unregister(&ep_dev->dev); destroy_endpoint_class(); return retval; @@ -348,7 +348,6 @@ void usb_remove_ep_files(struct usb_host_endpoint *endpoint) sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); sysfs_remove_link(&ep_dev->dev.parent->kobj, name); - sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp); device_unregister(&ep_dev->dev); endpoint->ep_dev = NULL; destroy_endpoint_class(); diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 3e69266..fe47d14 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1607,6 +1607,7 @@ free_interfaces: intf->dev.driver = NULL; intf->dev.bus = &usb_bus_type; intf->dev.type = &usb_if_device_type; + intf->dev.groups = usb_interface_groups; intf->dev.dma_mask = dev->dev.dma_mask; device_initialize(&intf->dev); mark_quiesced(intf); diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 5b20a60..c783cb1 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -538,6 +538,46 @@ static struct attribute_group dev_attr_grp = { .attrs = dev_attrs, }; +/* When modifying this list, be sure to modify dev_string_attrs_are_visible() + * accordingly. + */ +static struct attribute *dev_string_attrs[] = { + &dev_attr_manufacturer.attr, + &dev_attr_product.attr, + &dev_attr_serial.attr, + NULL +}; + +static mode_t dev_string_attrs_are_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct usb_device *udev = to_usb_device( + container_of(kobj, struct device, kobj)); + + if (a == &dev_attr_manufacturer.attr) { + if (udev->manufacturer == NULL) + return 0; + } else if (a == &dev_attr_product.attr) { + if (udev->product == NULL) + return 0; + } else if (a == &dev_attr_serial.attr) { + if (udev->serial == NULL) + return 0; + } + return a->mode; +} + +static struct attribute_group dev_string_attr_grp = { + .attrs = dev_string_attrs, + .is_visible = dev_string_attrs_are_visible, +}; + +struct attribute_group *usb_device_groups[] = { + &dev_attr_grp, + &dev_string_attr_grp, + NULL +}; + /* Binary descriptors */ static ssize_t @@ -591,10 +631,9 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) struct device *dev = &udev->dev; int retval; - retval = sysfs_create_group(&dev->kobj, &dev_attr_grp); - if (retval) - return retval; - + /* Unforunately these attributes cannot be created before + * the uevent is broadcast. + */ retval = device_create_bin_file(dev, &dev_bin_attr_descriptors); if (retval) goto error; @@ -607,21 +646,6 @@ int usb_create_sysfs_dev_files(struct usb_device *udev) if (retval) goto error; - if (udev->manufacturer) { - retval = device_create_file(dev, &dev_attr_manufacturer); - if (retval) - goto error; - } - if (udev->product) { - retval = device_create_file(dev, &dev_attr_product); - if (retval) - goto error; - } - if (udev->serial) { - retval = device_create_file(dev, &dev_attr_serial); - if (retval) - goto error; - } retval = usb_create_ep_files(dev, &udev->ep0, udev); if (retval) goto error; @@ -636,13 +660,9 @@ void usb_remove_sysfs_dev_files(struct usb_device *udev) struct device *dev = &udev->dev; usb_remove_ep_files(&udev->ep0); - device_remove_file(dev, &dev_attr_manufacturer); - device_remove_file(dev, &dev_attr_product); - device_remove_file(dev, &dev_attr_serial); remove_power_attributes(dev); remove_persist_attributes(dev); device_remove_bin_file(dev, &dev_bin_attr_descriptors); - sysfs_remove_group(&dev->kobj, &dev_attr_grp); } /* Interface Accociation Descriptor fields */ @@ -688,17 +708,15 @@ static ssize_t show_interface_string(struct device *dev, struct device_attribute *attr, char *buf) { struct usb_interface *intf; - struct usb_device *udev; - int len; + char *string; intf = to_usb_interface(dev); - udev = interface_to_usbdev(intf); - len = snprintf(buf, 256, "%s", intf->cur_altsetting->string); - if (len < 0) + string = intf->cur_altsetting->string; + barrier(); /* The altsetting might change! */ + + if (!string) return 0; - buf[len] = '\n'; - buf[len+1] = 0; - return len+1; + return sprintf(buf, "%s\n", string); } static DEVICE_ATTR(interface, S_IRUGO, show_interface_string, NULL); @@ -727,18 +745,6 @@ static ssize_t show_modalias(struct device *dev, } static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); -static struct attribute *intf_assoc_attrs[] = { - &dev_attr_iad_bFirstInterface.attr, - &dev_attr_iad_bInterfaceCount.attr, - &dev_attr_iad_bFunctionClass.attr, - &dev_attr_iad_bFunctionSubClass.attr, - &dev_attr_iad_bFunctionProtocol.attr, - NULL, -}; -static struct attribute_group intf_assoc_attr_grp = { - .attrs = intf_assoc_attrs, -}; - static struct attribute *intf_attrs[] = { &dev_attr_bInterfaceNumber.attr, &dev_attr_bAlternateSetting.attr, @@ -753,6 +759,37 @@ static struct attribute_group intf_attr_grp = { .attrs = intf_attrs, }; +static struct attribute *intf_assoc_attrs[] = { + &dev_attr_iad_bFirstInterface.attr, + &dev_attr_iad_bInterfaceCount.attr, + &dev_attr_iad_bFunctionClass.attr, + &dev_attr_iad_bFunctionSubClass.attr, + &dev_attr_iad_bFunctionProtocol.attr, + NULL, +}; + +static mode_t intf_assoc_attrs_are_visible(struct kobject *kobj, + struct attribute *a, int n) +{ + struct usb_interface *intf = to_usb_interface( + container_of(kobj, struct device, kobj)); + + if (intf->intf_assoc == NULL) + return 0; + return a->mode; +} + +static struct attribute_group intf_assoc_attr_grp = { + .attrs = intf_assoc_attrs, + .is_visible = intf_assoc_attrs_are_visible, +}; + +struct attribute_group *usb_interface_groups[] = { + &intf_attr_grp, + &intf_assoc_attr_grp, + NULL +}; + static inline void usb_create_intf_ep_files(struct usb_interface *intf, struct usb_device *udev) { @@ -777,23 +814,21 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf) int usb_create_sysfs_intf_files(struct usb_interface *intf) { - struct device *dev = &intf->dev; struct usb_device *udev = interface_to_usbdev(intf); struct usb_host_interface *alt = intf->cur_altsetting; int retval; if (intf->sysfs_files_created) return 0; - retval = sysfs_create_group(&dev->kobj, &intf_attr_grp); - if (retval) - return retval; + /* The interface string may be present in some altsettings + * and missing in others. Hence its attribute cannot be created + * before the uevent is broadcast. + */ if (alt->string == NULL) alt->string = usb_cache_string(udev, alt->desc.iInterface); if (alt->string) - retval = device_create_file(dev, &dev_attr_interface); - if (intf->intf_assoc) - retval = sysfs_create_group(&dev->kobj, &intf_assoc_attr_grp); + retval = device_create_file(&intf->dev, &dev_attr_interface); usb_create_intf_ep_files(intf, udev); intf->sysfs_files_created = 1; return 0; @@ -807,7 +842,5 @@ void usb_remove_sysfs_intf_files(struct usb_interface *intf) return; usb_remove_intf_ep_files(intf); device_remove_file(dev, &dev_attr_interface); - sysfs_remove_group(&dev->kobj, &intf_attr_grp); - sysfs_remove_group(&intf->dev.kobj, &intf_assoc_attr_grp); intf->sysfs_files_created = 0; } diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 1f0db51..3257743 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -291,6 +291,7 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, device_initialize(&dev->dev); dev->dev.bus = &usb_bus_type; dev->dev.type = &usb_device_type; + dev->dev.groups = usb_device_groups; dev->dev.dma_mask = bus->controller->dma_mask; set_dev_node(&dev->dev, dev_to_node(bus->controller)); dev->state = USB_STATE_ATTACHED; diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 1bf8ccb..1a8bc21 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -130,6 +130,10 @@ static inline int is_active(const struct usb_interface *f) /* for labeling diagnostics */ extern const char *usbcore_name; +/* sysfs stuff */ +extern struct attribute_group *usb_device_groups[]; +extern struct attribute_group *usb_interface_groups[]; + /* usbfs stuff */ extern struct mutex usbfs_mutex; extern struct usb_driver usbfs_driver; -- cgit v1.1 From d23039eec77473124c9635c01378314f196f2211 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 25 Apr 2008 19:23:16 -0700 Subject: USB: add association.h This will be used by the wireless usb code, as well as potentially other USB code. Originally based on some .c code written by Inaky Perez-Gonzalez Cc: Inaky Perez-Gonzalez Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- include/linux/usb/association.h | 150 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 include/linux/usb/association.h diff --git a/include/linux/usb/association.h b/include/linux/usb/association.h new file mode 100644 index 0000000..07c5e3c --- /dev/null +++ b/include/linux/usb/association.h @@ -0,0 +1,150 @@ +/* + * Wireless USB - Cable Based Association + * + * Copyright (C) 2006 Intel Corporation + * Inaky Perez-Gonzalez + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version + * 2 as published by the Free Software Foundation. + * + */ +#ifndef __LINUX_USB_ASSOCIATION_H +#define __LINUX_USB_ASSOCIATION_H + + +/* + * Association attributes + * + * Association Models Supplement to WUSB 1.0 T[3-1] + * + * Each field in the structures has it's ID, it's length and then the + * value. This is the actual definition of the field's ID and its + * length. + */ +struct wusb_am_attr { + __u8 id; + __u8 len; +}; + +/* Different fields defined by the spec */ +#define WUSB_AR_AssociationTypeId { .id = 0x0000, .len = 2 } +#define WUSB_AR_AssociationSubTypeId { .id = 0x0001, .len = 2 } +#define WUSB_AR_Length { .id = 0x0002, .len = 4 } +#define WUSB_AR_AssociationStatus { .id = 0x0004, .len = 4 } +#define WUSB_AR_LangID { .id = 0x0008, .len = 2 } +#define WUSB_AR_DeviceFriendlyName { .id = 0x000b, .len = 64 } /* max */ +#define WUSB_AR_HostFriendlyName { .id = 0x000c, .len = 64 } /* max */ +#define WUSB_AR_CHID { .id = 0x1000, .len = 16 } +#define WUSB_AR_CDID { .id = 0x1001, .len = 16 } +#define WUSB_AR_ConnectionContext { .id = 0x1002, .len = 48 } +#define WUSB_AR_BandGroups { .id = 0x1004, .len = 2 } + +/* CBAF Control Requests (AMS1.0[T4-1] */ +enum { + CBAF_REQ_GET_ASSOCIATION_INFORMATION = 0x01, + CBAF_REQ_GET_ASSOCIATION_REQUEST, + CBAF_REQ_SET_ASSOCIATION_RESPONSE +}; + +/* + * CBAF USB-interface defitions + * + * No altsettings, one optional interrupt endpoint. + */ +enum { + CBAF_IFACECLASS = 0xef, + CBAF_IFACESUBCLASS = 0x03, + CBAF_IFACEPROTOCOL = 0x01, +}; + +/* Association Information (AMS1.0[T4-3]) */ +struct wusb_cbaf_assoc_info { + __le16 Length; + __u8 NumAssociationRequests; + __le16 Flags; + __u8 AssociationRequestsArray[]; +} __attribute__((packed)); + +/* Association Request (AMS1.0[T4-4]) */ +struct wusb_cbaf_assoc_request { + __u8 AssociationDataIndex; + __u8 Reserved; + __le16 AssociationTypeId; + __le16 AssociationSubTypeId; + __le32 AssociationTypeInfoSize; +} __attribute__((packed)); + +enum { + AR_TYPE_WUSB = 0x0001, + AR_TYPE_WUSB_RETRIEVE_HOST_INFO = 0x0000, + AR_TYPE_WUSB_ASSOCIATE = 0x0001, +}; + +/* Association Attribute header (AMS1.0[3.8]) */ +struct wusb_cbaf_attr_hdr { + __le16 id; + __le16 len; +} __attribute__((packed)); + +/* Host Info (AMS1.0[T4-7]) (yeah, more headers and fields...) */ +struct wusb_cbaf_host_info { + struct wusb_cbaf_attr_hdr AssociationTypeId_hdr; + __le16 AssociationTypeId; + struct wusb_cbaf_attr_hdr AssociationSubTypeId_hdr; + __le16 AssociationSubTypeId; + struct wusb_cbaf_attr_hdr CHID_hdr; + struct wusb_ckhdid CHID; + struct wusb_cbaf_attr_hdr LangID_hdr; + __le16 LangID; + struct wusb_cbaf_attr_hdr HostFriendlyName_hdr; + __u8 HostFriendlyName[]; +} __attribute__((packed)); + +/* Device Info (AMS1.0[T4-8]) + * + * I still don't get this tag'n'header stuff for each goddamn + * field... + */ +struct wusb_cbaf_device_info { + struct wusb_cbaf_attr_hdr Length_hdr; + __le32 Length; + struct wusb_cbaf_attr_hdr CDID_hdr; + struct wusb_ckhdid CDID; + struct wusb_cbaf_attr_hdr BandGroups_hdr; + __le16 BandGroups; + struct wusb_cbaf_attr_hdr LangID_hdr; + __le16 LangID; + struct wusb_cbaf_attr_hdr DeviceFriendlyName_hdr; + __u8 DeviceFriendlyName[]; +} __attribute__((packed)); + +/* Connection Context; CC_DATA - Success case (AMS1.0[T4-9]) */ +struct wusb_cbaf_cc_data { + struct wusb_cbaf_attr_hdr AssociationTypeId_hdr; + __le16 AssociationTypeId; + struct wusb_cbaf_attr_hdr AssociationSubTypeId_hdr; + __le16 AssociationSubTypeId; + struct wusb_cbaf_attr_hdr Length_hdr; + __le32 Length; + struct wusb_cbaf_attr_hdr ConnectionContext_hdr; + struct wusb_ckhdid CHID; + struct wusb_ckhdid CDID; + struct wusb_ckhdid CK; + struct wusb_cbaf_attr_hdr BandGroups_hdr; + __le16 BandGroups; +} __attribute__((packed)); + +/* CC_DATA - Failure case (AMS1.0[T4-10]) */ +struct wusb_cbaf_cc_data_fail { + struct wusb_cbaf_attr_hdr AssociationTypeId_hdr; + __le16 AssociationTypeId; + struct wusb_cbaf_attr_hdr AssociationSubTypeId_hdr; + __le16 AssociationSubTypeId; + struct wusb_cbaf_attr_hdr Length_hdr; + __le16 Length; + struct wusb_cbaf_attr_hdr AssociationStatus_hdr; + __u32 AssociationStatus; +} __attribute__((packed)); + +#endif /* __LINUX_USB_ASSOCIATION_H */ -- cgit v1.1 From 23cacd65f65956426bbca25964a68c174db83a31 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 8 May 2008 23:03:04 +0200 Subject: USB: add Telstra NextG CDMA id to option driver As reported by Magnus Boman Cc: Magnus Boman Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e4be2d4..118dfe2 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -301,6 +301,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */ + { USB_DEVICE(0x19d2, 0x0001) }, /* Telstra NextG CDMA */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, option_ids); -- cgit v1.1 From 220264733d3fb126c5ffd71ce897d918ce491c62 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 30 Apr 2008 13:53:54 -0700 Subject: USB: isp1760: fix printk format Fix printk format warnings in isp1760 (in linux-next): next-20080430/drivers/usb/host/isp1760-hcd.c:994: warning: format '%d' expects type 'int', but argument 6 has type 'size_t' next-20080430/drivers/usb/host/isp1760-hcd.c:1092: warning: format '%d' expects type 'int', but argument 3 has type 'size_t' Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1760-hcd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 4ba96c1..c9cec87 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -988,7 +988,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd) * This did not trigger for a long time now. */ printk(KERN_ERR "Reloading ptd %p/%p... qh %p readed: " - "%d of %d done: %08x cur: %08x\n", qtd, + "%d of %zu done: %08x cur: %08x\n", qtd, urb, qh, PTD_XFERRED_LENGTH(dw3), qtd->length, done_map, (1 << queue_entry)); @@ -1088,7 +1088,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd) } else if (usb_pipebulk(urb->pipe) && (length < qtd->length)) { /* short BULK received */ - printk(KERN_ERR "short bulk, %d instead %d\n", length, + printk(KERN_ERR "short bulk, %d instead %zu\n", length, qtd->length); if (urb->transfer_flags & URB_SHORT_NOT_OK) { urb->status = -EREMOTEIO; -- cgit v1.1 From af3d305ca71fea5dfdeba4bcecf2f91fa16dfa9d Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 30 Apr 2008 15:03:41 -0700 Subject: usb: fix integer as NULL pointer warnings found by sparse drivers/usb/host/ohci-sm501.c:93:24: warning: Using plain integer as NULL pointer drivers/usb/gadget/amd5536udc.c:3254:9: warning: Using plain integer as NULL pointer drivers/usb/gadget/amd5536udc.c:3267:9: warning: Using plain integer as NULL pointer drivers/usb/gadget/amd5536udc.c:3277:9: warning: Using plain integer as NULL pointer drivers/usb/gadget/amd5536udc.c:3285:9: warning: Using plain integer as NULL pointer drivers/usb/gadget/amd5536udc.c:3293:9: warning: Using plain integer as NULL pointer Signed-off-by: Harvey Harrison Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/amd5536udc.c | 10 +++++----- drivers/usb/host/ohci-sm501.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index ce337cb..f261d2a 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -3251,7 +3251,7 @@ static int udc_pci_probe( /* pci setup */ if (pci_enable_device(pdev) < 0) { kfree(dev); - dev = 0; + dev = NULL; retval = -ENODEV; goto finished; } @@ -3264,7 +3264,7 @@ static int udc_pci_probe( if (!request_mem_region(resource, len, name)) { dev_dbg(&pdev->dev, "pci device used already\n"); kfree(dev); - dev = 0; + dev = NULL; retval = -EBUSY; goto finished; } @@ -3274,7 +3274,7 @@ static int udc_pci_probe( if (dev->virt_addr == NULL) { dev_dbg(&pdev->dev, "start address cannot be mapped\n"); kfree(dev); - dev = 0; + dev = NULL; retval = -EFAULT; goto finished; } @@ -3282,7 +3282,7 @@ static int udc_pci_probe( if (!pdev->irq) { dev_err(&dev->pdev->dev, "irq not set\n"); kfree(dev); - dev = 0; + dev = NULL; retval = -ENODEV; goto finished; } @@ -3290,7 +3290,7 @@ static int udc_pci_probe( if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) { dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq); kfree(dev); - dev = 0; + dev = NULL; retval = -EBUSY; goto finished; } diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index 77204f0..e899a77 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -90,7 +90,7 @@ static int ohci_hcd_sm501_drv_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct resource *res, *mem; int retval, irq; - struct usb_hcd *hcd = 0; + struct usb_hcd *hcd = NULL; irq = retval = platform_get_irq(pdev, 0); if (retval < 0) -- cgit v1.1 From dddcb8b7d419b6726ba07efe53e6bb216a9e86cb Mon Sep 17 00:00:00 2001 From: "andreoli@samba.ing.unimo.it" Date: Thu, 1 May 2008 19:17:28 +0200 Subject: USB: Support for the ET502HS HDSPA modem The attached patch allows to bypass the ZeroCD mechanism for the ET502HS HDSPA modem, so that it can be mounted as a network device. Signed-off-by: Mauro Andreolini Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index a0ed889..dfdc0e5 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1684,6 +1684,16 @@ UNUSUAL_DEV( 0x1652, 0x6600, 0x0201, 0x0201, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +/* Reported by Mauro Andreolini + * This entry is needed to bypass the ZeroCD mechanism + * and to properly load as a modem device. + */ +UNUSUAL_DEV( 0x19d2, 0x2000, 0x0000, 0x0000, + "Onda ET502HS", + "USB MMC Storage", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_IGNORE_DEVICE), + /* patch submitted by Davide Perini * and Renato Perini */ -- cgit v1.1 From 4c7d3137fe4fce634d55a6e99c95dff4c6306702 Mon Sep 17 00:00:00 2001 From: "andreoli@samba.ing.unimo.it" Date: Thu, 1 May 2008 19:26:16 +0200 Subject: USB: Support for the ET502HS HDSPA modem in option driver the proposed patch allows the ET502HS HDSPA modem to be handled by the "option" driver. It has been tested for 1 month and works reliably (no oopses, no hangs, 300KB/s throughput). Signed-off-by: Mauro Andreolini Signed-off-by: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 118dfe2..f56da4c 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -184,6 +184,9 @@ static int option_send_setup(struct usb_serial_port *port); #define AXESSTEL_VENDOR_ID 0x1726 #define AXESSTEL_PRODUCT_MV110H 0x1000 +#define ONDA_VENDOR_ID 0x19d2 +#define ONDA_PRODUCT_ET502HS 0x0002 + #define BANDRICH_VENDOR_ID 0x1A8D #define BANDRICH_PRODUCT_C100_1 0x1002 #define BANDRICH_PRODUCT_C100_2 0x1003 @@ -296,6 +299,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) }, + { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_1) }, { USB_DEVICE(BANDRICH_VENDOR_ID, BANDRICH_PRODUCT_C100_2) }, { USB_DEVICE(KYOCERA_VENDOR_ID, KYOCERA_PRODUCT_KPC680) }, -- cgit v1.1 From 6149ed5e3a6207595bd7362af7724d64f44af216 Mon Sep 17 00:00:00 2001 From: Iain McFarlane Date: Sun, 4 May 2008 00:13:49 +0100 Subject: USB: add Zoom Telephonics Model 3095F V.92 USB Mini External modem to cdc-acm The patch below is a necessary workaround to support the Zoom Telephonics Model 3095F V.92 USB Mini External modem, which fails to initialise properly during normal probing thus: May 3 22:53:00 imcfarla kernel: drivers/usb/class/cdc-acm.c: Zero length descriptor references May 3 22:53:00 imcfarla kernel: cdc_acm: probe of 5-2:1.0 failed with error -22 Adding the patch below causes the probing section to be skipped, and the modem then initialises correctly. Signed-off-by: Iain McFarlane Acked-by: Oliver Neukum Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index cefe7f2..63c3404 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1248,6 +1248,9 @@ static struct usb_device_id acm_ids[] = { { USB_DEVICE(0x22b8, 0x7000), /* Motorola Q Phone */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, + { USB_DEVICE(0x0803, 0x3095), /* Zoom Telephonics Model 3095F USB MODEM */ + .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ + }, /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, -- cgit v1.1 From ed3e8fcaeb67b7c2c96eb9c30d5b98816a08a1a2 Mon Sep 17 00:00:00 2001 From: Phil Dibowitz Date: Sat, 3 May 2008 18:04:30 -0700 Subject: USB: Fix unusual_devs.h ordering This patch fixes ordering problems with entries in unusual_devs.h. Signed-off-by: Phil Dibowitz Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 51 +++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index dfdc0e5..de01023 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -401,6 +401,14 @@ UNUSUAL_DEV( 0x04a5, 0x3010, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE ), +#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB +UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999, + "Cypress", + "Cypress AT2LP", + US_SC_CYP_ATACB, US_PR_BULK, NULL, + 0), +#endif + /* Reported by Simon Levitt * This entry needs Sub and Proto fields */ UNUSUAL_DEV( 0x04b8, 0x0601, 0x0100, 0x0100, @@ -539,17 +547,6 @@ UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200, "CD-RW Device", US_SC_8020, US_PR_CB, NULL, 0), -/* Entry and supporting patch by Theodore Kilgore . - * Device uses standards-violating 32-byte Bulk Command Block Wrappers and - * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011. - */ - -UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x0100, - "Kobian Mercury", - "Binocam DCB-132", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_BULK32), - #ifdef CONFIG_USB_STORAGE_USBAT UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, "Shuttle/SCM", @@ -565,6 +562,16 @@ UNUSUAL_DEV( 0x04e8, 0x507c, 0x0220, 0x0220, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64), +/* Entry and supporting patch by Theodore Kilgore . + * Device uses standards-violating 32-byte Bulk Command Block Wrappers and + * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011. + */ +UNUSUAL_DEV( 0x04fc, 0x80c2, 0x0100, 0x0100, + "Kobian Mercury", + "Binocam DCB-132", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_BULK32), + /* Reported by Bob Sass -- only rev 1.33 tested */ UNUSUAL_DEV( 0x050d, 0x0115, 0x0133, 0x0133, "Belkin", @@ -1361,13 +1368,6 @@ UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY), -/* Reported by Rohan Hart */ -UNUSUAL_DEV( 0x2770, 0x915d, 0x0010, 0x0010, - "INTOVA", - "Pixtreme", - US_SC_DEVICE, US_PR_DEVICE, NULL, - US_FL_FIX_CAPACITY ), - /* * Entry for Jenoptik JD 5200z3 * @@ -1731,6 +1731,13 @@ UNUSUAL_DEV( 0x2735, 0x100b, 0x0000, 0x9999, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_GO_SLOW ), +/* Reported by Rohan Hart */ +UNUSUAL_DEV( 0x2770, 0x915d, 0x0010, 0x0010, + "INTOVA", + "Pixtreme", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_CAPACITY ), + /* * David Härdeman * The key makes the SCSI stack print confusing (but harmless) messages @@ -1755,14 +1762,6 @@ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_CAPACITY_HEURISTICS), -#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB -UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999, - "Cypress", - "Cypress AT2LP", - US_SC_CYP_ATACB, US_PR_BULK, NULL, - 0), -#endif - /* Control/Bulk transport for all SubClass values */ USUAL_DEV(US_SC_RBC, US_PR_CB, USB_US_TYPE_STOR), USUAL_DEV(US_SC_8020, US_PR_CB, USB_US_TYPE_STOR), -- cgit v1.1 From cdafc37a7b727b75ced65e31e47dafbd8b70f97f Mon Sep 17 00:00:00 2001 From: Eugeniy Meshcheryakov Date: Mon, 5 May 2008 01:24:38 +0200 Subject: USB: do not handle device 1410:5010 in 'option' driver This device is not a serial port, but a virtual CD-ROM device. For example with my Novatel MC950D: lsusb -v -d 1410:5010 | grep InterfaceClass bInterfaceClass 8 Mass Storage After some time (ca. 5min) or if virtual CD is ejected, device id changes to 1410:4400: % lsusb -v -d 1410:4400 | grep InterfaceClass bInterfaceClass 255 Vendor Specific Class bInterfaceClass 255 Vendor Specific Class Variable name says that 0x5010 is a Novatel U727, but searching in internet shows, that this device also provides virtual CD that should be ejected before use. Product id for serial port in this case is 0x4100. Signed-off-by: Eugeniy Meshcheryakov Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index f56da4c..8bf831b 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -154,8 +154,6 @@ static int option_send_setup(struct usb_serial_port *port); #define NOVATELWIRELESS_PRODUCT_MC727 0x4100 #define NOVATELWIRELESS_PRODUCT_MC950D 0x4400 -#define NOVATELWIRELESS_PRODUCT_U727 0x5010 - /* FUTURE NOVATEL PRODUCTS */ #define NOVATELWIRELESS_PRODUCT_EVDO_1 0x6000 #define NOVATELWIRELESS_PRODUCT_HSPA_1 0x7000 @@ -272,7 +270,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */ - { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel U727 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_1) }, /* Novatel EVDO product */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_1) }, /* Novatel HSPA product */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EMBEDDED_1) }, /* Novatel Embedded product */ -- cgit v1.1 From fe312e77f0ed4349e908b1575be0d4308f0b2ce4 Mon Sep 17 00:00:00 2001 From: Sebastian Siewior Date: Mon, 5 May 2008 09:31:50 +0200 Subject: usb: fix compile warning in isp1760 drivers/usb/host/isp1760-if.c:275: warning: 'ret' is used uninitialized in this function Signed-off-by: Sebastian Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1760-if.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 73fb2a3..440bf94 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -256,7 +256,7 @@ static struct pci_driver isp1761_pci_driver = { static int __init isp1760_init(void) { - int ret; + int ret = -ENODEV; init_kmem_once(); -- cgit v1.1 From 9079e91b5b5a84836e65cdc9128d2602e3beaef2 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 7 May 2008 16:00:36 -0700 Subject: USB: serial gadget: cleanup/reorg Some cleanup/reorg of g_serial ... simplifying it, and disentangling its structure so morphing it into a "function" driver (combinable with other interfaces) should be less painful. - Remove most forward declarations * put tty and gadget driver structs after their contents * snug module init/exit decls next to their functions * reordered some functions - Other cleanup: * convert a funky macro to an inline function * snug up module params next to their declarations * add missing driver.owner * add separator lines between major driver sections - Add comments re potential parameter/#define changes: * only supports one port (shrank GS_NUM_PORTS) * changing from 9600-8-N-1 affects multiple sites - Remove net2280-specific optimization ... it was being done way too late, can be done by net2280 module options, and in any case doesn't matter at any sane serial data rates. There are no behavioral changes, but the macro thing saves I-space. Signed-off-by: David Brownell Cc: Al Borchers Cc: Alan Cox Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/serial.c | 553 +++++++++++++++++++++----------------------- 1 file changed, 263 insertions(+), 290 deletions(-) diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 54cdd6f..00da3f6 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -14,7 +14,6 @@ * This software is distributed under the terms of the GNU General * Public License ("GPL") as published by the Free Software Foundation, * either version 2 of that License or (at your option) any later version. - * */ #include @@ -41,7 +40,11 @@ #define GS_MAJOR 127 #define GS_MINOR_START 0 -#define GS_NUM_PORTS 16 +/* REVISIT only one port is supported for now; + * see gs_{send,recv}_packet() ... no multiplexing, + * and no support for multiple ACM devices. + */ +#define GS_NUM_PORTS 1 #define GS_NUM_CONFIGS 1 #define GS_NO_CONFIG_ID 0 @@ -65,6 +68,9 @@ #define GS_DEFAULT_USE_ACM 0 +/* 9600-8-N-1 ... matches init_termios.c_cflag and defaults + * expected by "usbser.sys" on MS-Windows. + */ #define GS_DEFAULT_DTE_RATE 9600 #define GS_DEFAULT_DATA_BITS 8 #define GS_DEFAULT_PARITY USB_CDC_NO_PARITY @@ -107,10 +113,6 @@ static int debug = 1; #define GS_NOTIFY_MAXPACKET 8 -/* Structures */ - -struct gs_dev; - /* circular buffer */ struct gs_buf { unsigned int buf_size; @@ -164,26 +166,7 @@ struct gs_dev { /* Functions */ -/* module */ -static int __init gs_module_init(void); -static void __exit gs_module_exit(void); - -/* tty driver */ -static int gs_open(struct tty_struct *tty, struct file *file); -static void gs_close(struct tty_struct *tty, struct file *file); -static int gs_write(struct tty_struct *tty, - const unsigned char *buf, int count); -static int gs_put_char(struct tty_struct *tty, unsigned char ch); -static void gs_flush_chars(struct tty_struct *tty); -static int gs_write_room(struct tty_struct *tty); -static int gs_chars_in_buffer(struct tty_struct *tty); -static void gs_throttle(struct tty_struct * tty); -static void gs_unthrottle(struct tty_struct * tty); -static void gs_break(struct tty_struct *tty, int break_state); -static int gs_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg); -static void gs_set_termios(struct tty_struct *tty, struct ktermios *old); - +/* tty driver internals */ static int gs_send(struct gs_dev *dev); static int gs_send_packet(struct gs_dev *dev, char *packet, unsigned int size); @@ -192,19 +175,7 @@ static int gs_recv_packet(struct gs_dev *dev, char *packet, static void gs_read_complete(struct usb_ep *ep, struct usb_request *req); static void gs_write_complete(struct usb_ep *ep, struct usb_request *req); -/* gadget driver */ -static int gs_bind(struct usb_gadget *gadget); -static void gs_unbind(struct usb_gadget *gadget); -static int gs_setup(struct usb_gadget *gadget, - const struct usb_ctrlrequest *ctrl); -static int gs_setup_standard(struct usb_gadget *gadget, - const struct usb_ctrlrequest *ctrl); -static int gs_setup_class(struct usb_gadget *gadget, - const struct usb_ctrlrequest *ctrl); -static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req); -static void gs_setup_complete_set_line_coding(struct usb_ep *ep, - struct usb_request *req); -static void gs_disconnect(struct usb_gadget *gadget); +/* gadget driver internals */ static int gs_set_config(struct gs_dev *dev, unsigned config); static void gs_reset_config(struct gs_dev *dev); static int gs_build_config_buf(u8 *buf, struct usb_gadget *g, @@ -232,9 +203,6 @@ static unsigned int gs_buf_put(struct gs_buf *gb, const char *buf, static unsigned int gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count); -/* external functions */ -extern int net2280_set_fifo_mode(struct usb_gadget *gadget, int mode); - /* Globals */ @@ -246,48 +214,8 @@ static const char *EP_NOTIFY_NAME; static struct mutex gs_open_close_lock[GS_NUM_PORTS]; -static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE; -static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE; - -static unsigned int write_buf_size = GS_DEFAULT_WRITE_BUF_SIZE; - -static unsigned int use_acm = GS_DEFAULT_USE_ACM; - - -/* tty driver struct */ -static const struct tty_operations gs_tty_ops = { - .open = gs_open, - .close = gs_close, - .write = gs_write, - .put_char = gs_put_char, - .flush_chars = gs_flush_chars, - .write_room = gs_write_room, - .ioctl = gs_ioctl, - .set_termios = gs_set_termios, - .throttle = gs_throttle, - .unthrottle = gs_unthrottle, - .break_ctl = gs_break, - .chars_in_buffer = gs_chars_in_buffer, -}; -static struct tty_driver *gs_tty_driver; - -/* gadget driver struct */ -static struct usb_gadget_driver gs_gadget_driver = { -#ifdef CONFIG_USB_GADGET_DUALSPEED - .speed = USB_SPEED_HIGH, -#else - .speed = USB_SPEED_FULL, -#endif /* CONFIG_USB_GADGET_DUALSPEED */ - .function = GS_LONG_NAME, - .bind = gs_bind, - .unbind = gs_unbind, - .setup = gs_setup, - .disconnect = gs_disconnect, - .driver = { - .name = GS_SHORT_NAME, - }, -}; +/*-------------------------------------------------------------------------*/ /* USB descriptors */ @@ -521,6 +449,8 @@ static const struct usb_descriptor_header *gs_acm_highspeed_function[] = { }; +/*-------------------------------------------------------------------------*/ + /* Module */ MODULE_DESCRIPTION(GS_LONG_NAME); MODULE_AUTHOR("Al Borchers"); @@ -531,84 +461,23 @@ module_param(debug, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(debug, "Enable debugging, 0=off, 1=on"); #endif +static unsigned int read_q_size = GS_DEFAULT_READ_Q_SIZE; module_param(read_q_size, uint, S_IRUGO); MODULE_PARM_DESC(read_q_size, "Read request queue size, default=32"); +static unsigned int write_q_size = GS_DEFAULT_WRITE_Q_SIZE; module_param(write_q_size, uint, S_IRUGO); MODULE_PARM_DESC(write_q_size, "Write request queue size, default=32"); +static unsigned int write_buf_size = GS_DEFAULT_WRITE_BUF_SIZE; module_param(write_buf_size, uint, S_IRUGO); MODULE_PARM_DESC(write_buf_size, "Write buffer size, default=8192"); +static unsigned int use_acm = GS_DEFAULT_USE_ACM; module_param(use_acm, uint, S_IRUGO); MODULE_PARM_DESC(use_acm, "Use CDC ACM, 0=no, 1=yes, default=no"); -module_init(gs_module_init); -module_exit(gs_module_exit); - -/* -* gs_module_init -* -* Register as a USB gadget driver and a tty driver. -*/ -static int __init gs_module_init(void) -{ - int i; - int retval; - - retval = usb_gadget_register_driver(&gs_gadget_driver); - if (retval) { - pr_err("gs_module_init: cannot register gadget driver, " - "ret=%d\n", retval); - return retval; - } - - gs_tty_driver = alloc_tty_driver(GS_NUM_PORTS); - if (!gs_tty_driver) - return -ENOMEM; - gs_tty_driver->owner = THIS_MODULE; - gs_tty_driver->driver_name = GS_SHORT_NAME; - gs_tty_driver->name = "ttygs"; - gs_tty_driver->major = GS_MAJOR; - gs_tty_driver->minor_start = GS_MINOR_START; - gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; - gs_tty_driver->subtype = SERIAL_TYPE_NORMAL; - gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; - gs_tty_driver->init_termios = tty_std_termios; - gs_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; - tty_set_operations(gs_tty_driver, &gs_tty_ops); - - for (i=0; i < GS_NUM_PORTS; i++) - mutex_init(&gs_open_close_lock[i]); - - retval = tty_register_driver(gs_tty_driver); - if (retval) { - usb_gadget_unregister_driver(&gs_gadget_driver); - put_tty_driver(gs_tty_driver); - pr_err("gs_module_init: cannot register tty driver, " - "ret=%d\n", retval); - return retval; - } - - pr_info("gs_module_init: %s %s loaded\n", - GS_LONG_NAME, GS_VERSION_STR); - return 0; -} - -/* -* gs_module_exit -* -* Unregister as a tty driver and a USB gadget driver. -*/ -static void __exit gs_module_exit(void) -{ - tty_unregister_driver(gs_tty_driver); - put_tty_driver(gs_tty_driver); - usb_gadget_unregister_driver(&gs_gadget_driver); - - pr_info("gs_module_exit: %s %s unloaded\n", - GS_LONG_NAME, GS_VERSION_STR); -} +/*-------------------------------------------------------------------------*/ /* TTY Driver */ @@ -753,15 +622,15 @@ exit_unlock_dev: * gs_close */ -#define GS_WRITE_FINISHED_EVENT_SAFELY(p) \ -({ \ - int cond; \ - \ - spin_lock_irq(&(p)->port_lock); \ - cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf); \ - spin_unlock_irq(&(p)->port_lock); \ - cond; \ -}) +static int gs_write_finished_event_safely(struct gs_port *p) +{ + int cond; + + spin_lock_irq(&(p)->port_lock); + cond = !(p)->port_dev || !gs_buf_data_avail((p)->port_write_buf); + spin_unlock_irq(&(p)->port_lock); + return cond; +} static void gs_close(struct tty_struct *tty, struct file *file) { @@ -807,7 +676,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) if (gs_buf_data_avail(port->port_write_buf) > 0) { spin_unlock_irq(&port->port_lock); wait_event_interruptible_timeout(port->port_write_wait, - GS_WRITE_FINISHED_EVENT_SAFELY(port), + gs_write_finished_event_safely(port), GS_CLOSE_TIMEOUT * HZ); spin_lock_irq(&port->port_lock); } @@ -1065,6 +934,23 @@ static void gs_set_termios(struct tty_struct *tty, struct ktermios *old) { } +static const struct tty_operations gs_tty_ops = { + .open = gs_open, + .close = gs_close, + .write = gs_write, + .put_char = gs_put_char, + .flush_chars = gs_flush_chars, + .write_room = gs_write_room, + .ioctl = gs_ioctl, + .set_termios = gs_set_termios, + .throttle = gs_throttle, + .unthrottle = gs_unthrottle, + .break_ctl = gs_break, + .chars_in_buffer = gs_chars_in_buffer, +}; + +/*-------------------------------------------------------------------------*/ + /* * gs_send * @@ -1328,9 +1214,44 @@ requeue: } } +/*-------------------------------------------------------------------------*/ + /* Gadget Driver */ /* + * gs_unbind + * + * Called on module unload. Frees the control request and device + * structure. + */ +static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget) +{ + struct gs_dev *dev = get_gadget_data(gadget); + + gs_device = NULL; + + /* read/write requests already freed, only control request remains */ + if (dev != NULL) { + if (dev->dev_ctrl_req != NULL) { + gs_free_req(gadget->ep0, dev->dev_ctrl_req); + dev->dev_ctrl_req = NULL; + } + gs_free_ports(dev); + if (dev->dev_notify_ep) + usb_ep_disable(dev->dev_notify_ep); + if (dev->dev_in_ep) + usb_ep_disable(dev->dev_in_ep); + if (dev->dev_out_ep) + usb_ep_disable(dev->dev_out_ep); + kfree(dev); + set_gadget_data(gadget, NULL); + } + + pr_info("gs_unbind: %s %s unbound\n", GS_LONG_NAME, + GS_VERSION_STR); +} + +/* * gs_bind * * Called on module load. Allocates and initializes the device @@ -1441,8 +1362,6 @@ static int __init gs_bind(struct usb_gadget *gadget) gs_unbind(gadget); return -ENOMEM; } - dev->dev_ctrl_req->complete = gs_setup_complete; - gadget->ep0->driver_data = dev; pr_info("gs_bind: %s %s bound\n", @@ -1455,95 +1374,6 @@ autoconf_fail: return -ENODEV; } -/* - * gs_unbind - * - * Called on module unload. Frees the control request and device - * structure. - */ -static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget) -{ - struct gs_dev *dev = get_gadget_data(gadget); - - gs_device = NULL; - - /* read/write requests already freed, only control request remains */ - if (dev != NULL) { - if (dev->dev_ctrl_req != NULL) { - gs_free_req(gadget->ep0, dev->dev_ctrl_req); - dev->dev_ctrl_req = NULL; - } - gs_free_ports(dev); - if (dev->dev_notify_ep) - usb_ep_disable(dev->dev_notify_ep); - if (dev->dev_in_ep) - usb_ep_disable(dev->dev_in_ep); - if (dev->dev_out_ep) - usb_ep_disable(dev->dev_out_ep); - kfree(dev); - set_gadget_data(gadget, NULL); - } - - pr_info("gs_unbind: %s %s unbound\n", GS_LONG_NAME, - GS_VERSION_STR); -} - -/* - * gs_setup - * - * Implements all the control endpoint functionality that's not - * handled in hardware or the hardware driver. - * - * Returns the size of the data sent to the host, or a negative - * error number. - */ -static int gs_setup(struct usb_gadget *gadget, - const struct usb_ctrlrequest *ctrl) -{ - int ret = -EOPNOTSUPP; - struct gs_dev *dev = get_gadget_data(gadget); - struct usb_request *req = dev->dev_ctrl_req; - u16 wIndex = le16_to_cpu(ctrl->wIndex); - u16 wValue = le16_to_cpu(ctrl->wValue); - u16 wLength = le16_to_cpu(ctrl->wLength); - - req->complete = gs_setup_complete; - - switch (ctrl->bRequestType & USB_TYPE_MASK) { - case USB_TYPE_STANDARD: - ret = gs_setup_standard(gadget,ctrl); - break; - - case USB_TYPE_CLASS: - ret = gs_setup_class(gadget,ctrl); - break; - - default: - pr_err("gs_setup: unknown request, type=%02x, request=%02x, " - "value=%04x, index=%04x, length=%d\n", - ctrl->bRequestType, ctrl->bRequest, - wValue, wIndex, wLength); - break; - } - - /* respond with data transfer before status phase? */ - if (ret >= 0) { - req->length = ret; - req->zero = ret < wLength - && (ret % gadget->ep0->maxpacket) == 0; - ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); - if (ret < 0) { - pr_err("gs_setup: cannot queue response, ret=%d\n", - ret); - req->status = 0; - gs_setup_complete(gadget->ep0, req); - } - } - - /* device either stalls (ret < 0) or reports success */ - return ret; -} - static int gs_setup_standard(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) { @@ -1673,6 +1503,42 @@ set_interface_done: return ret; } +static void gs_setup_complete_set_line_coding(struct usb_ep *ep, + struct usb_request *req) +{ + struct gs_dev *dev = ep->driver_data; + struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */ + + switch (req->status) { + case 0: + /* normal completion */ + if (req->actual != sizeof(port->port_line_coding)) + usb_ep_set_halt(ep); + else if (port) { + struct usb_cdc_line_coding *value = req->buf; + + /* REVISIT: we currently just remember this data. + * If we change that, (a) validate it first, then + * (b) update whatever hardware needs updating. + */ + spin_lock(&port->port_lock); + port->port_line_coding = *value; + spin_unlock(&port->port_lock); + } + break; + + case -ESHUTDOWN: + /* disconnect */ + gs_free_req(ep, req); + break; + + default: + /* unexpected */ + break; + } + return; +} + static int gs_setup_class(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) { @@ -1734,52 +1600,72 @@ static int gs_setup_class(struct usb_gadget *gadget, return ret; } -static void gs_setup_complete_set_line_coding(struct usb_ep *ep, - struct usb_request *req) +/* + * gs_setup_complete + */ +static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req) { - struct gs_dev *dev = ep->driver_data; - struct gs_port *port = dev->dev_port[0]; /* ACM only has one port */ + if (req->status || req->actual != req->length) { + pr_err("gs_setup_complete: status error, status=%d, " + "actual=%d, length=%d\n", + req->status, req->actual, req->length); + } +} - switch (req->status) { - case 0: - /* normal completion */ - if (req->actual != sizeof(port->port_line_coding)) - usb_ep_set_halt(ep); - else if (port) { - struct usb_cdc_line_coding *value = req->buf; +/* + * gs_setup + * + * Implements all the control endpoint functionality that's not + * handled in hardware or the hardware driver. + * + * Returns the size of the data sent to the host, or a negative + * error number. + */ +static int gs_setup(struct usb_gadget *gadget, + const struct usb_ctrlrequest *ctrl) +{ + int ret = -EOPNOTSUPP; + struct gs_dev *dev = get_gadget_data(gadget); + struct usb_request *req = dev->dev_ctrl_req; + u16 wIndex = le16_to_cpu(ctrl->wIndex); + u16 wValue = le16_to_cpu(ctrl->wValue); + u16 wLength = le16_to_cpu(ctrl->wLength); - /* REVISIT: we currently just remember this data. - * If we change that, (a) validate it first, then - * (b) update whatever hardware needs updating. - */ - spin_lock(&port->port_lock); - port->port_line_coding = *value; - spin_unlock(&port->port_lock); - } + req->complete = gs_setup_complete; + + switch (ctrl->bRequestType & USB_TYPE_MASK) { + case USB_TYPE_STANDARD: + ret = gs_setup_standard(gadget, ctrl); break; - case -ESHUTDOWN: - /* disconnect */ - gs_free_req(ep, req); + case USB_TYPE_CLASS: + ret = gs_setup_class(gadget, ctrl); break; default: - /* unexpected */ + pr_err("gs_setup: unknown request, type=%02x, request=%02x, " + "value=%04x, index=%04x, length=%d\n", + ctrl->bRequestType, ctrl->bRequest, + wValue, wIndex, wLength); break; } - return; -} -/* - * gs_setup_complete - */ -static void gs_setup_complete(struct usb_ep *ep, struct usb_request *req) -{ - if (req->status || req->actual != req->length) { - pr_err("gs_setup_complete: status error, status=%d, " - "actual=%d, length=%d\n", - req->status, req->actual, req->length); + /* respond with data transfer before status phase? */ + if (ret >= 0) { + req->length = ret; + req->zero = ret < wLength + && (ret % gadget->ep0->maxpacket) == 0; + ret = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); + if (ret < 0) { + pr_err("gs_setup: cannot queue response, ret=%d\n", + ret); + req->status = 0; + gs_setup_complete(gadget->ep0, req); + } } + + /* device either stalls (ret < 0) or reports success */ + return ret; } /* @@ -1811,6 +1697,23 @@ static void gs_disconnect(struct usb_gadget *gadget) pr_info("gs_disconnect: %s disconnected\n", GS_LONG_NAME); } +static struct usb_gadget_driver gs_gadget_driver = { +#ifdef CONFIG_USB_GADGET_DUALSPEED + .speed = USB_SPEED_HIGH, +#else + .speed = USB_SPEED_FULL, +#endif /* CONFIG_USB_GADGET_DUALSPEED */ + .function = GS_LONG_NAME, + .bind = gs_bind, + .unbind = gs_unbind, + .setup = gs_setup, + .disconnect = gs_disconnect, + .driver = { + .name = GS_SHORT_NAME, + .owner = THIS_MODULE, + }, +}; + /* * gs_set_config * @@ -1846,16 +1749,10 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) case GS_BULK_CONFIG_ID: if (use_acm) return -EINVAL; - /* device specific optimizations */ - if (gadget_is_net2280(gadget)) - net2280_set_fifo_mode(gadget, 1); break; case GS_ACM_CONFIG_ID: if (!use_acm) return -EINVAL; - /* device specific optimizations */ - if (gadget_is_net2280(gadget)) - net2280_set_fifo_mode(gadget, 1); break; default: return -EINVAL; @@ -2233,6 +2130,8 @@ static void gs_free_ports(struct gs_dev *dev) } } +/*-------------------------------------------------------------------------*/ + /* Circular Buffer */ /* @@ -2393,3 +2292,77 @@ gs_buf_get(struct gs_buf *gb, char *buf, unsigned int count) return count; } + +/*-------------------------------------------------------------------------*/ + +static struct tty_driver *gs_tty_driver; + +/* + * gs_module_init + * + * Register as a USB gadget driver and a tty driver. + */ +static int __init gs_module_init(void) +{ + int i; + int retval; + + retval = usb_gadget_register_driver(&gs_gadget_driver); + if (retval) { + pr_err("gs_module_init: cannot register gadget driver, " + "ret=%d\n", retval); + return retval; + } + + gs_tty_driver = alloc_tty_driver(GS_NUM_PORTS); + if (!gs_tty_driver) + return -ENOMEM; + gs_tty_driver->owner = THIS_MODULE; + gs_tty_driver->driver_name = GS_SHORT_NAME; + gs_tty_driver->name = "ttygs"; + gs_tty_driver->major = GS_MAJOR; + gs_tty_driver->minor_start = GS_MINOR_START; + gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + gs_tty_driver->subtype = SERIAL_TYPE_NORMAL; + gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + gs_tty_driver->init_termios = tty_std_termios; + /* must match GS_DEFAULT_DTE_RATE and friends */ + gs_tty_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + gs_tty_driver->init_termios.c_ispeed = GS_DEFAULT_DTE_RATE; + gs_tty_driver->init_termios.c_ospeed = GS_DEFAULT_DTE_RATE; + tty_set_operations(gs_tty_driver, &gs_tty_ops); + + for (i = 0; i < GS_NUM_PORTS; i++) + mutex_init(&gs_open_close_lock[i]); + + retval = tty_register_driver(gs_tty_driver); + if (retval) { + usb_gadget_unregister_driver(&gs_gadget_driver); + put_tty_driver(gs_tty_driver); + pr_err("gs_module_init: cannot register tty driver, " + "ret=%d\n", retval); + return retval; + } + + pr_info("gs_module_init: %s %s loaded\n", + GS_LONG_NAME, GS_VERSION_STR); + return 0; +} +module_init(gs_module_init); + +/* + * gs_module_exit + * + * Unregister as a tty driver and a USB gadget driver. + */ +static void __exit gs_module_exit(void) +{ + tty_unregister_driver(gs_tty_driver); + put_tty_driver(gs_tty_driver); + usb_gadget_unregister_driver(&gs_gadget_driver); + + pr_info("gs_module_exit: %s %s unloaded\n", + GS_LONG_NAME, GS_VERSION_STR); +} +module_exit(gs_module_exit); -- cgit v1.1 From 2c2d28a015f0dd36c5d1a06e16923e3142574066 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 7 May 2008 14:24:10 -0700 Subject: USB: serial gadget: remove needless data structure This removes a needless data structure from the serial gadget code; it's a small code shrink, and a larger data shrink. Since "struct usb_request" already has a "struct list_head" reserved for use by gadget drivers, the serial gadget code doesn't need to allocate wrapper structs to hold that list ... it can (and should!) just use the list_head provided for that exact use. Signed-off-by: David Brownell Cc: Al Borchers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/serial.c | 85 +++++++-------------------------------------- 1 file changed, 13 insertions(+), 72 deletions(-) diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 00da3f6..b0c32c7 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -121,12 +121,6 @@ struct gs_buf { char *buf_put; }; -/* list of requests */ -struct gs_req_entry { - struct list_head re_entry; - struct usb_request *re_req; -}; - /* the port structure holds info for each port, one for each minor number */ struct gs_port { struct gs_dev *port_dev; /* pointer to device struct */ @@ -185,10 +179,6 @@ static struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned int len, gfp_t kmalloc_flags); static void gs_free_req(struct usb_ep *ep, struct usb_request *req); -static struct gs_req_entry *gs_alloc_req_entry(struct usb_ep *ep, unsigned len, - gfp_t kmalloc_flags); -static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req); - static int gs_alloc_ports(struct gs_dev *dev, gfp_t kmalloc_flags); static void gs_free_ports(struct gs_dev *dev); @@ -966,7 +956,6 @@ static int gs_send(struct gs_dev *dev) unsigned long flags; struct usb_ep *ep; struct usb_request *req; - struct gs_req_entry *req_entry; if (dev == NULL) { pr_err("gs_send: NULL device pointer\n"); @@ -979,10 +968,8 @@ static int gs_send(struct gs_dev *dev) while(!list_empty(&dev->dev_req_list)) { - req_entry = list_entry(dev->dev_req_list.next, - struct gs_req_entry, re_entry); - - req = req_entry->re_req; + req = list_entry(dev->dev_req_list.next, + struct usb_request, list); len = gs_send_packet(dev, req->buf, ep->maxpacket); @@ -992,7 +979,7 @@ static int gs_send(struct gs_dev *dev) *((unsigned char *)req->buf), *((unsigned char *)req->buf+1), *((unsigned char *)req->buf+2)); - list_del(&req_entry->re_entry); + list_del(&req->list); req->length = len; spin_unlock_irqrestore(&dev->dev_lock, flags); if ((ret=usb_ep_queue(ep, req, GFP_ATOMIC))) { @@ -1175,7 +1162,6 @@ requeue: static void gs_write_complete(struct usb_ep *ep, struct usb_request *req) { struct gs_dev *dev = ep->driver_data; - struct gs_req_entry *gs_req = req->context; if (dev == NULL) { pr_err("gs_write_complete: NULL device pointer\n"); @@ -1186,13 +1172,8 @@ static void gs_write_complete(struct usb_ep *ep, struct usb_request *req) case 0: /* normal completion */ requeue: - if (gs_req == NULL) { - pr_err("gs_write_complete: NULL request pointer\n"); - return; - } - spin_lock(&dev->dev_lock); - list_add(&gs_req->re_entry, &dev->dev_req_list); + list_add(&req->list, &dev->dev_req_list); spin_unlock(&dev->dev_lock); gs_send(dev); @@ -1731,7 +1712,6 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) struct usb_ep *ep; struct usb_endpoint_descriptor *ep_desc; struct usb_request *req; - struct gs_req_entry *req_entry; if (dev == NULL) { pr_err("gs_set_config: NULL device pointer\n"); @@ -1843,9 +1823,10 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) /* allocate write requests, and put on free list */ ep = dev->dev_in_ep; for (i=0; imaxpacket, GFP_ATOMIC))) { - req_entry->re_req->complete = gs_write_complete; - list_add(&req_entry->re_entry, &dev->dev_req_list); + req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC); + if (req) { + req->complete = gs_write_complete; + list_add(&req->list, &dev->dev_req_list); } else { pr_err("gs_set_config: cannot allocate " "write requests\n"); @@ -1883,7 +1864,7 @@ exit_reset_config: */ static void gs_reset_config(struct gs_dev *dev) { - struct gs_req_entry *req_entry; + struct usb_request *req; if (dev == NULL) { pr_err("gs_reset_config: NULL device pointer\n"); @@ -1897,10 +1878,10 @@ static void gs_reset_config(struct gs_dev *dev) /* free write requests on the free list */ while(!list_empty(&dev->dev_req_list)) { - req_entry = list_entry(dev->dev_req_list.next, - struct gs_req_entry, re_entry); - list_del(&req_entry->re_entry); - gs_free_req_entry(dev->dev_in_ep, req_entry); + req = list_entry(dev->dev_req_list.next, + struct usb_request, list); + list_del(&req->list); + gs_free_req(dev->dev_in_ep, req); } /* disable endpoints, forcing completion of pending i/o; */ @@ -2010,46 +1991,6 @@ static void gs_free_req(struct usb_ep *ep, struct usb_request *req) } /* - * gs_alloc_req_entry - * - * Allocates a request and its buffer, using the given - * endpoint, buffer len, and kmalloc flags. - */ -static struct gs_req_entry * -gs_alloc_req_entry(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags) -{ - struct gs_req_entry *req; - - req = kmalloc(sizeof(struct gs_req_entry), kmalloc_flags); - if (req == NULL) - return NULL; - - req->re_req = gs_alloc_req(ep, len, kmalloc_flags); - if (req->re_req == NULL) { - kfree(req); - return NULL; - } - - req->re_req->context = req; - - return req; -} - -/* - * gs_free_req_entry - * - * Frees a request and its buffer. - */ -static void gs_free_req_entry(struct usb_ep *ep, struct gs_req_entry *req) -{ - if (ep != NULL && req != NULL) { - if (req->re_req != NULL) - gs_free_req(ep, req->re_req); - kfree(req); - } -} - -/* * gs_alloc_ports * * Allocate all ports and set the gs_dev struct to point to them. -- cgit v1.1 From 734d37c654569f03156f8603a9761c402a73aa20 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 7 May 2008 14:25:24 -0700 Subject: USB: serial gadget: simplify endpoint handling Switch serial gadget away from a *very* old idiom: just remember the endpoints we'll be using, instead of looking them up by name each time. This is a net code and data (globals) shrink. Also fix a small memory leak in the rmmod path, by working the same as the disconnect code. Signed-off-by: David Brownell Cc: Al Borchers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/serial.c | 146 +++++++++++++++++--------------------------- 1 file changed, 57 insertions(+), 89 deletions(-) diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index b0c32c7..0829027 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -198,10 +198,6 @@ static unsigned int gs_buf_get(struct gs_buf *gb, char *buf, static struct gs_dev *gs_device; -static const char *EP_IN_NAME; -static const char *EP_OUT_NAME; -static const char *EP_NOTIFY_NAME; - static struct mutex gs_open_close_lock[GS_NUM_PORTS]; @@ -1217,13 +1213,8 @@ static void /* __init_or_exit */ gs_unbind(struct usb_gadget *gadget) gs_free_req(gadget->ep0, dev->dev_ctrl_req); dev->dev_ctrl_req = NULL; } + gs_reset_config(dev); gs_free_ports(dev); - if (dev->dev_notify_ep) - usb_ep_disable(dev->dev_notify_ep); - if (dev->dev_in_ep) - usb_ep_disable(dev->dev_in_ep); - if (dev->dev_out_ep) - usb_ep_disable(dev->dev_out_ep); kfree(dev); set_gadget_data(gadget, NULL); } @@ -1264,19 +1255,23 @@ static int __init gs_bind(struct usb_gadget *gadget) __constant_cpu_to_le16(GS_VERSION_NUM|0x0099); } + dev = kzalloc(sizeof(struct gs_dev), GFP_KERNEL); + if (dev == NULL) + return -ENOMEM; + usb_ep_autoconfig_reset(gadget); ep = usb_ep_autoconfig(gadget, &gs_fullspeed_in_desc); if (!ep) goto autoconf_fail; - EP_IN_NAME = ep->name; - ep->driver_data = ep; /* claim the endpoint */ + dev->dev_in_ep = ep; + ep->driver_data = dev; /* claim the endpoint */ ep = usb_ep_autoconfig(gadget, &gs_fullspeed_out_desc); if (!ep) goto autoconf_fail; - EP_OUT_NAME = ep->name; - ep->driver_data = ep; /* claim the endpoint */ + dev->dev_out_ep = ep; + ep->driver_data = dev; /* claim the endpoint */ if (use_acm) { ep = usb_ep_autoconfig(gadget, &gs_fullspeed_notify_desc); @@ -1286,8 +1281,8 @@ static int __init gs_bind(struct usb_gadget *gadget) } gs_device_desc.idProduct = __constant_cpu_to_le16( GS_CDC_PRODUCT_ID), - EP_NOTIFY_NAME = ep->name; - ep->driver_data = ep; /* claim the endpoint */ + dev->dev_notify_ep = ep; + ep->driver_data = dev; /* claim the endpoint */ } gs_device_desc.bDeviceClass = use_acm @@ -1317,9 +1312,7 @@ static int __init gs_bind(struct usb_gadget *gadget) gs_acm_config_desc.bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - gs_device = dev = kzalloc(sizeof(struct gs_dev), GFP_KERNEL); - if (dev == NULL) - return -ENOMEM; + gs_device = dev; snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s", init_utsname()->sysname, init_utsname()->release, @@ -1351,6 +1344,7 @@ static int __init gs_bind(struct usb_gadget *gadget) return 0; autoconf_fail: + kfree(dev); pr_err("gs_bind: cannot autoconfigure on %s\n", gadget->name); return -ENODEV; } @@ -1710,7 +1704,7 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) int ret = 0; struct usb_gadget *gadget = dev->dev_gadget; struct usb_ep *ep; - struct usb_endpoint_descriptor *ep_desc; + struct usb_endpoint_descriptor *out, *in, *notify; struct usb_request *req; if (dev == NULL) { @@ -1738,71 +1732,53 @@ static int gs_set_config(struct gs_dev *dev, unsigned config) return -EINVAL; } - dev->dev_config = config; - - gadget_for_each_ep(ep, gadget) { - - if (EP_NOTIFY_NAME - && strcmp(ep->name, EP_NOTIFY_NAME) == 0) { - ep_desc = choose_ep_desc(gadget, + in = choose_ep_desc(gadget, + &gs_highspeed_in_desc, + &gs_fullspeed_in_desc); + out = choose_ep_desc(gadget, + &gs_highspeed_out_desc, + &gs_fullspeed_out_desc); + notify = dev->dev_notify_ep + ? choose_ep_desc(gadget, &gs_highspeed_notify_desc, - &gs_fullspeed_notify_desc); - ret = usb_ep_enable(ep,ep_desc); - if (ret == 0) { - ep->driver_data = dev; - dev->dev_notify_ep = ep; - dev->dev_notify_ep_desc = ep_desc; - } else { - pr_err("gs_set_config: cannot enable NOTIFY " - "endpoint %s, ret=%d\n", - ep->name, ret); - goto exit_reset_config; - } - } + &gs_fullspeed_notify_desc) + : NULL; - else if (strcmp(ep->name, EP_IN_NAME) == 0) { - ep_desc = choose_ep_desc(gadget, - &gs_highspeed_in_desc, - &gs_fullspeed_in_desc); - ret = usb_ep_enable(ep,ep_desc); - if (ret == 0) { - ep->driver_data = dev; - dev->dev_in_ep = ep; - dev->dev_in_ep_desc = ep_desc; - } else { - pr_err("gs_set_config: cannot enable IN " - "endpoint %s, ret=%d\n", - ep->name, ret); - goto exit_reset_config; - } - } - - else if (strcmp(ep->name, EP_OUT_NAME) == 0) { - ep_desc = choose_ep_desc(gadget, - &gs_highspeed_out_desc, - &gs_fullspeed_out_desc); - ret = usb_ep_enable(ep,ep_desc); - if (ret == 0) { - ep->driver_data = dev; - dev->dev_out_ep = ep; - dev->dev_out_ep_desc = ep_desc; - } else { - pr_err("gs_set_config: cannot enable OUT " - "endpoint %s, ret=%d\n", - ep->name, ret); - goto exit_reset_config; - } - } + ret = usb_ep_enable(dev->dev_in_ep, in); + if (ret == 0) { + dev->dev_in_ep_desc = in; + } else { + pr_debug("%s: cannot enable %s %s, ret=%d\n", + __func__, "IN", dev->dev_in_ep->name, ret); + return ret; + } + ret = usb_ep_enable(dev->dev_out_ep, out); + if (ret == 0) { + dev->dev_out_ep_desc = out; + } else { + pr_debug("%s: cannot enable %s %s, ret=%d\n", + __func__, "OUT", dev->dev_out_ep->name, ret); +fail0: + usb_ep_disable(dev->dev_in_ep); + return ret; } - if (dev->dev_in_ep == NULL || dev->dev_out_ep == NULL - || (config != GS_BULK_CONFIG_ID && dev->dev_notify_ep == NULL)) { - pr_err("gs_set_config: cannot find endpoints\n"); - ret = -ENODEV; - goto exit_reset_config; + if (notify) { + ret = usb_ep_enable(dev->dev_notify_ep, notify); + if (ret == 0) { + dev->dev_notify_ep_desc = notify; + } else { + pr_debug("%s: cannot enable %s %s, ret=%d\n", + __func__, "NOTIFY", + dev->dev_notify_ep->name, ret); + usb_ep_disable(dev->dev_out_ep); + goto fail0; + } } + dev->dev_config = config; + /* allocate and queue read requests */ ep = dev->dev_out_ep; for (i=0; idev_notify_ep) { + if (dev->dev_notify_ep) usb_ep_disable(dev->dev_notify_ep); - dev->dev_notify_ep = NULL; - } - if (dev->dev_in_ep) { - usb_ep_disable(dev->dev_in_ep); - dev->dev_in_ep = NULL; - } - if (dev->dev_out_ep) { - usb_ep_disable(dev->dev_out_ep); - dev->dev_out_ep = NULL; - } + usb_ep_disable(dev->dev_in_ep); + usb_ep_disable(dev->dev_out_ep); } /* -- cgit v1.1 From b9370332f4879360ef7126f7a19c660e87084290 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 7 May 2008 14:27:37 -0700 Subject: USB: serial gadget: descriptor cleanup Bugfix some serial gadget descriptors: - Stop mangling the low bits (controller type ID) of bcdDevice; just use the high bits for a driver revision code. - Serial numbers that aren't specific to individual devices are useless; stop reporting "0" for this. - Since it's not part of a CDC-conformant function, the "bulk only" configuration shouldn't be using "CDC Data" as its interface class. Switch over to using CLASS_VENDOR_SPEC (different value, 0xff). Signed-off-by: David Brownell Cc: Al Borchers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/serial.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 0829027..fa019fa 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -32,7 +32,7 @@ /* Defines */ #define GS_VERSION_STR "v2.2" -#define GS_VERSION_NUM 0x0202 +#define GS_VERSION_NUM 0x2200 #define GS_LONG_NAME "Gadget Serial" #define GS_SHORT_NAME "g_serial" @@ -218,7 +218,6 @@ static char manufacturer[50]; static struct usb_string gs_strings[] = { { GS_MANUFACTURER_STR_ID, manufacturer }, { GS_PRODUCT_STR_ID, GS_LONG_NAME }, - { GS_SERIAL_STR_ID, "0" }, { GS_BULK_CONFIG_STR_ID, "Gadget Serial Bulk" }, { GS_ACM_CONFIG_STR_ID, "Gadget Serial CDC ACM" }, { GS_CONTROL_STR_ID, "Gadget Serial Control" }, @@ -241,7 +240,6 @@ static struct usb_device_descriptor gs_device_desc = { .idProduct = __constant_cpu_to_le16(GS_PRODUCT_ID), .iManufacturer = GS_MANUFACTURER_STR_ID, .iProduct = GS_PRODUCT_STR_ID, - .iSerialNumber = GS_SERIAL_STR_ID, .bNumConfigurations = GS_NUM_CONFIGS, }; @@ -278,7 +276,7 @@ static const struct usb_interface_descriptor gs_bulk_interface_desc = { .bDescriptorType = USB_DT_INTERFACE, .bInterfaceNumber = GS_BULK_INTERFACE_ID, .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceClass = USB_CLASS_VENDOR_SPEC, .bInterfaceSubClass = 0, .bInterfaceProtocol = 0, .iInterface = GS_DATA_STR_ID, -- cgit v1.1 From e7c6f80fd733218aa1e79efa5d9ece9f76966160 Mon Sep 17 00:00:00 2001 From: Filip Aben Date: Thu, 8 May 2008 10:48:12 -0700 Subject: USB: unusual_devs: Add support for GI 0401 SD-Card interface Enables the SD-Card interface on the GI 0401 HSUPA card from Option. The unusual_devs.h entry is necessary because the device descriptor is vendor-specific. That prevents usb-storage from binding to it as an interface driver. This revised patch adds a small comment explaining why and reduces the rev range. T: Bus=02 Lev=01 Prnt=01 Port=06 Cnt=01 Dev#= 3 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=ff Prot=ff MxPS=64 #Cfgs= 1 P: Vendor=0af0 ProdID=7401 Rev= 0.00 S: Manufacturer=Option N.V. S: Product=Globetrotter HSUPA Modem C:* #Ifs=10 Cfg#= 1 Atr=80 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 0 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 1 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 1 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 2 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 2 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 3 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 3 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 4 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 4 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 5 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 5 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 6 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 6 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 7 Alt= 0 #EPs= 0 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) I: If#= 7 Alt= 1 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=08(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 8 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=89(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=8a(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=09(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 9 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=0a(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8b(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: Filip Aben Signed-off-by: Phil Dibowitz Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index de01023..1b09578 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1311,6 +1311,16 @@ UNUSUAL_DEV( 0x0ace, 0x20ff, 0x0101, 0x0101, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_DEVICE ), +/* Reported by F. Aben + * This device (wrongly) has a vendor-specific device descriptor. + * The entry is needed so usb-storage can bind to it's mass-storage + * interface as an interface driver */ +UNUSUAL_DEV( 0x0af0, 0x7401, 0x0000, 0x0000, + "Option", + "GI 0401 SD-Card", + US_SC_DEVICE, US_PR_DEVICE, NULL, + 0 ), + #ifdef CONFIG_USB_STORAGE_ISD200 UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, "ATI", -- cgit v1.1 From 96cb15cf977356d9d3117dd88f3fe187d6024f4b Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 13 May 2008 12:53:45 -0400 Subject: USB: option: add new Dell 5520 HSDPA variant New variant of the 5520 found by Luke Sheldrick. Signed-off-by: Dan Williams Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 8bf831b..e7e016e 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -293,6 +293,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, 0x8133) }, /* Dell Wireless 5720 == Novatel EV620 CDMA/EV-DO */ { USB_DEVICE(DELL_VENDOR_ID, 0x8136) }, /* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */ { USB_DEVICE(DELL_VENDOR_ID, 0x8137) }, /* Dell Wireless HSDPA 5520 */ + { USB_DEVICE(DELL_VENDOR_ID, 0x8138) }, /* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) }, -- cgit v1.1 From 5fc89390f74ac42165db477793fb30f6a200e79c Mon Sep 17 00:00:00 2001 From: Xiaofan Chen Date: Tue, 13 May 2008 21:52:00 +0800 Subject: USB: remove PICDEM FS USB demo (04d8:000c) device from ldusb Microchip has changed the PICDEM FS USB demo device (0x04d8:000c) to use bulk transfer and not interrupt transfer. So I've updated the libusb based program here (Post #31). http://forum.microchip.com/tm.aspx?m=106426&mpage=2 So I believe that the in-kernel ldusb driver will no longer work with the demo firmware. It should be removed. Signed-off-by: Xiaofan Chen Cc: Michael Hund Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/ldusb.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 7aafd53..189a9db 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -63,9 +63,6 @@ #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 #define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006 -#define USB_VENDOR_ID_MICROCHIP 0x04d8 -#define USB_DEVICE_ID_PICDEM 0x000c - #ifdef CONFIG_USB_DYNAMIC_MINORS #define USB_LD_MINOR_BASE 0 #else @@ -92,7 +89,6 @@ static struct usb_device_id ld_usb_table [] = { { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) }, - { USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICDEM) }, { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) }, { } /* Terminating entry */ }; -- cgit v1.1 From 6def755320a214ae149ad6bc69eb8c1d7887e678 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Mon, 12 May 2008 20:17:25 +0200 Subject: usbtest: comment on why this code "expects" negative and positive errnos On Mon, May 12, 2008 at 01:02:22AM -0700, David Brownell wrote: > On Sunday 11 May 2008, Marcin Slusarz wrote: > > > > test_ctrl_queue expects (?) positive and negative errnos. > > what is going on here? > > The sign is just a way to flag something: > > /* some faults are allowed, not required */ > > The negative ones are required. Positive codes are optional, > in the sense that, depending on how the peripheral happens > to be implemented, they won't necessarily be triggered. > > For example, the test to fetch a device qualifier desriptor > must succeed if the device is running at high speed. So that > test is marked as negative. But when it's full speed, it > could legitimately fail; marked as positive. And so on for > other tests. > > Look at how the codes are *interpreted* to see it work. Lets document it. Based on comment from David Brownell . Signed-off-by: Marcin Slusarz Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/usbtest.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 742be3c..054dedd 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c @@ -856,6 +856,11 @@ test_ctrl_queue (struct usbtest_dev *dev, struct usbtest_param *param) struct urb *u; struct usb_ctrlrequest req; struct subcase *reqp; + + /* sign of this variable means: + * -: tested code must return this (negative) error code + * +: tested code may return this (negative too) error code + */ int expected = 0; /* requests here are mostly expected to succeed on any -- cgit v1.1 From 5a59bc544d00923ff715e2fe68ea537153f52dda Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Mon, 12 May 2008 10:47:56 -0700 Subject: USB: pxa27x_udc: minor fixes Minor fixes to pxa27x udc driver : - don't clobber driver model bus_id field - wrong endianess fix (no functional change; cpu is little-endian) - double udc disable fix - resume/suspend fix (OTG hold bit) - make driver pxa27x dependant (check cpu at runtime) Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 17 ++++++++--------- drivers/usb/gadget/pxa27x_udc.h | 8 ++++++++ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 75eba20..499b7a2 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1546,7 +1546,6 @@ static __init void udc_init_data(struct pxa_udc *dev) INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); dev->udc_usb_ep[0].pxa_ep = &dev->pxa_ep[0]; ep0_idle(dev); - strcpy(dev->dev->bus_id, ""); /* PXA endpoints init */ for (i = 0; i < NR_PXA_ENDPOINTS; i++) { @@ -1746,13 +1745,10 @@ static void handle_ep0_ctrl_req(struct pxa_udc *udc, ep_err(ep, "wrong to have extra bytes for setup : 0x%08x\n", i); } - le16_to_cpus(&u.r.wValue); - le16_to_cpus(&u.r.wIndex); - le16_to_cpus(&u.r.wLength); - ep_dbg(ep, "SETUP %02x.%02x v%04x i%04x l%04x\n", u.r.bRequestType, u.r.bRequest, - u.r.wValue, u.r.wIndex, u.r.wLength); + le16_to_cpu(u.r.wValue), le16_to_cpu(u.r.wIndex), + le16_to_cpu(u.r.wLength)); if (unlikely(have_extrabytes)) goto stall; @@ -2296,7 +2292,8 @@ static void pxa_udc_shutdown(struct platform_device *_dev) { struct pxa_udc *udc = platform_get_drvdata(_dev); - udc_disable(udc); + if (udc_readl(udc, UDCCR) & UDCCR_UDE) + udc_disable(udc); } #ifdef CONFIG_PM @@ -2361,9 +2358,8 @@ static int pxa_udc_resume(struct platform_device *_dev) * Upon exit from sleep mode and before clearing OTGPH, * Software must configure the USB OTG pad, UDC, and UHC * to the state they were in before entering sleep mode. - * - * Should be : PSSR |= PSSR_OTGPH; */ + PSSR |= PSSR_OTGPH; return 0; } @@ -2387,6 +2383,9 @@ static struct platform_driver udc_driver = { static int __init udc_init(void) { + if (!cpu_is_pxa27x()) + return -ENODEV; + printk(KERN_INFO "%s: version %s\n", driver_name, DRIVER_VERSION); return platform_driver_probe(&udc_driver, pxa_udc_probe); } diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index 1d1b793..97453db 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -484,4 +484,12 @@ static inline struct pxa_udc *to_gadget_udc(struct usb_gadget *gadget) #define ep_warn(ep, fmt, arg...) \ dev_warn(ep->dev->dev, "%s:%s:" fmt, EPNAME(ep), __func__, ## arg) +/* + * Cannot include pxa-regs.h, as register names are similar. + * So PSSR is redefined here. This should be removed once UDC registers will + * be gone from pxa-regs.h. + */ +#define PSSR __REG(0x40F00004) /* Power Manager Sleep Status */ +#define PSSR_OTGPH (1 << 6) /* OTG Peripheral Hold */ + #endif /* __LINUX_USB_GADGET_PXA27X_H */ -- cgit v1.1 From 405177070614f35133304d4daa1332afeb83ffa2 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sat, 10 May 2008 22:46:38 -0700 Subject: USB: atmel_usba_udc fixes, mostly disconnect() Various fixes to Atmel's high speed UDC driver. * Issue some missing disconnect() calls. Currently they are only made when VBUS power goes away (on boards where the driver can sense such changes), but that's not enough for gadget drivers to clean out all the state that's needed. Missing calls were: - After USB reset, before starting enumeration. - When unregistering a gadget driver, before unbind(). * Don't assume gadget drivers provide disconnect callbacks; make sure to not call through a null pointer! * When the driver doesn't provide an unbind() callback, refuse to unregister it. Also remove two bogus "error" messages: * Related to mis-handling of disconnect() ... don't emit error messages for disconnect() handlers that disable endpoints. All of them should be doing that; the problem is (unfixed) oddness in atmel_usba_udc. * Don't emit a diagnostic for a curious and transient nonfatal error that shows up sometimes with EP0. Those messages spammed syslog, for no good reason. Signed-off-by: David Brownell Acked-by: Haavard Skinnemoen Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/atmel_usba_udc.c | 48 +++++++++++++++++++++++++++++-------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index e756023..07e5a0b 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -649,7 +649,13 @@ static int usba_ep_disable(struct usb_ep *_ep) if (!ep->desc) { spin_unlock_irqrestore(&udc->lock, flags); - DBG(DBG_ERR, "ep_disable: %s not enabled\n", ep->ep.name); + /* REVISIT because this driver disables endpoints in + * reset_all_endpoints() before calling disconnect(), + * most gadget drivers would trigger this non-error ... + */ + if (udc->gadget.speed != USB_SPEED_UNKNOWN) + DBG(DBG_ERR, "ep_disable: %s not enabled\n", + ep->ep.name); return -EINVAL; } ep->desc = NULL; @@ -1032,8 +1038,6 @@ static struct usba_udc the_udc = { .release = nop_release, }, }, - - .lock = SPIN_LOCK_UNLOCKED, }; /* @@ -1052,6 +1056,12 @@ static void reset_all_endpoints(struct usba_udc *udc) request_complete(ep, req, -ECONNRESET); } + /* NOTE: normally, the next call to the gadget driver is in + * charge of disabling endpoints... usually disconnect(). + * The exception would be entering a high speed test mode. + * + * FIXME remove this code ... and retest thoroughly. + */ list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { if (ep->desc) { spin_unlock(&udc->lock); @@ -1219,7 +1229,7 @@ static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq) static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, struct usb_ctrlrequest *crq) { - int retval = 0;; + int retval = 0; switch (crq->bRequest) { case USB_REQ_GET_STATUS: { @@ -1693,6 +1703,14 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) usba_writel(udc, INT_CLR, USBA_END_OF_RESET); reset_all_endpoints(udc); + if (udc->gadget.speed != USB_SPEED_UNKNOWN + && udc->driver->disconnect) { + udc->gadget.speed = USB_SPEED_UNKNOWN; + spin_unlock(&udc->lock); + udc->driver->disconnect(&udc->gadget); + spin_lock(&udc->lock); + } + if (status & USBA_HIGH_SPEED) { DBG(DBG_BUS, "High-speed bus reset detected\n"); udc->gadget.speed = USB_SPEED_HIGH; @@ -1716,9 +1734,13 @@ static irqreturn_t usba_udc_irq(int irq, void *devid) | USBA_DET_SUSPEND | USBA_END_OF_RESUME)); + /* + * Unclear why we hit this irregularly, e.g. in usbtest, + * but it's clearly harmless... + */ if (!(usba_ep_readl(ep0, CFG) & USBA_EPT_MAPPED)) - dev_warn(&udc->pdev->dev, - "WARNING: EP0 configuration is invalid!\n"); + dev_dbg(&udc->pdev->dev, + "ODD: EP0 configuration is invalid!\n"); } spin_unlock(&udc->lock); @@ -1751,9 +1773,11 @@ static irqreturn_t usba_vbus_irq(int irq, void *devid) reset_all_endpoints(udc); toggle_bias(0); usba_writel(udc, CTRL, USBA_DISABLE_MASK); - spin_unlock(&udc->lock); - udc->driver->disconnect(&udc->gadget); - spin_lock(&udc->lock); + if (udc->driver->disconnect) { + spin_unlock(&udc->lock); + udc->driver->disconnect(&udc->gadget); + spin_lock(&udc->lock); + } } udc->vbus_prev = vbus; } @@ -1825,7 +1849,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) if (!udc->pdev) return -ENODEV; - if (driver != udc->driver) + if (driver != udc->driver || !driver->unbind) return -EINVAL; if (udc->vbus_pin != -1) @@ -1840,6 +1864,9 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) toggle_bias(0); usba_writel(udc, CTRL, USBA_DISABLE_MASK); + if (udc->driver->disconnect) + udc->driver->disconnect(&udc->gadget); + driver->unbind(&udc->gadget); udc->gadget.dev.driver = NULL; udc->driver = NULL; @@ -1879,6 +1906,7 @@ static int __init usba_udc_probe(struct platform_device *pdev) goto err_get_hclk; } + spin_lock_init(&udc->lock); udc->pdev = pdev; udc->pclk = pclk; udc->hclk = hclk; -- cgit v1.1 From 73f10281ea96d7e8b4fc1c5d755a7c8eb484155b Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 14 May 2008 06:35:11 +0200 Subject: read_barrier_depends arch fixlets read_barrie_depends has always been a noop (not a compiler barrier) on all architectures except SMP alpha. This brings UP alpha and frv into line with all other architectures, and fixes incorrect documentation. Signed-off-by: Nick Piggin Acked-by: Paul E. McKenney Signed-off-by: Linus Torvalds --- Documentation/memory-barriers.txt | 12 +++++++++++- include/asm-alpha/barrier.h | 2 +- include/asm-frv/system.h | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index e5a819a..f5b7127 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -994,7 +994,17 @@ The Linux kernel has eight basic CPU memory barriers: DATA DEPENDENCY read_barrier_depends() smp_read_barrier_depends() -All CPU memory barriers unconditionally imply compiler barriers. +All memory barriers except the data dependency barriers imply a compiler +barrier. Data dependencies do not impose any additional compiler ordering. + +Aside: In the case of data dependencies, the compiler would be expected to +issue the loads in the correct order (eg. `a[b]` would have to load the value +of b before loading a[b]), however there is no guarantee in the C specification +that the compiler may not speculate the value of b (eg. is equal to 1) and load +a before b (eg. tmp = a[1]; if (b != 1) tmp = a[b]; ). There is also the +problem of a compiler reloading b after having loaded a[b], thus having a newer +copy of b than a[b]. A consensus has not yet been reached about these problems, +however the ACCESS_ONCE macro is a good place to start looking. SMP memory barriers are reduced to compiler barriers on uniprocessor compiled systems because it is assumed that a CPU will appear to be self-consistent, diff --git a/include/asm-alpha/barrier.h b/include/asm-alpha/barrier.h index 384dc08d..ac78eba 100644 --- a/include/asm-alpha/barrier.h +++ b/include/asm-alpha/barrier.h @@ -24,7 +24,7 @@ __asm__ __volatile__("mb": : :"memory") #define smp_mb() barrier() #define smp_rmb() barrier() #define smp_wmb() barrier() -#define smp_read_barrier_depends() barrier() +#define smp_read_barrier_depends() do { } while (0) #endif #define set_mb(var, value) \ diff --git a/include/asm-frv/system.h b/include/asm-frv/system.h index cb307f8..d3a12a9 100644 --- a/include/asm-frv/system.h +++ b/include/asm-frv/system.h @@ -179,7 +179,7 @@ do { \ #define mb() asm volatile ("membar" : : :"memory") #define rmb() asm volatile ("membar" : : :"memory") #define wmb() asm volatile ("membar" : : :"memory") -#define read_barrier_depends() barrier() +#define read_barrier_depends() do { } while (0) #ifdef CONFIG_SMP #define smp_mb() mb() -- cgit v1.1 From 362a61ad61199e19a61b8e432015e2586b288f5b Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Wed, 14 May 2008 06:37:36 +0200 Subject: fix SMP data race in pagetable setup vs walking There is a possible data race in the page table walking code. After the split ptlock patches, it actually seems to have been introduced to the core code, but even before that I think it would have impacted some architectures (powerpc and sparc64, at least, walk the page tables without taking locks eg. see find_linux_pte()). The race is as follows: The pte page is allocated, zeroed, and its struct page gets its spinlock initialized. The mm-wide ptl is then taken, and then the pte page is inserted into the pagetables. At this point, the spinlock is not guaranteed to have ordered the previous stores to initialize the pte page with the subsequent store to put it in the page tables. So another Linux page table walker might be walking down (without any locks, because we have split-leaf-ptls), and find that new pte we've inserted. It might try to take the spinlock before the store from the other CPU initializes it. And subsequently it might read a pte_t out before stores from the other CPU have cleared the memory. There are also similar races in higher levels of the page tables. They obviously don't involve the spinlock, but could see uninitialized memory. Arch code and hardware pagetable walkers that walk the pagetables without locks could see similar uninitialized memory problems, regardless of whether split ptes are enabled or not. I prefer to put the barriers in core code, because that's where the higher level logic happens, but the page table accessors are per-arch, and open-coding them everywhere I don't think is an option. I'll put the read-side barriers in alpha arch code for now (other architectures perform data-dependent loads in order). Signed-off-by: Nick Piggin Signed-off-by: Linus Torvalds --- include/asm-alpha/pgtable.h | 21 +++++++++++++++++++-- mm/memory.c | 21 +++++++++++++++++++++ 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h index 05ce5fb..3f0c59f6 100644 --- a/include/asm-alpha/pgtable.h +++ b/include/asm-alpha/pgtable.h @@ -287,17 +287,34 @@ extern inline pte_t pte_mkspecial(pte_t pte) { return pte; } #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD-1)) #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address)) +/* + * The smp_read_barrier_depends() in the following functions are required to + * order the load of *dir (the pointer in the top level page table) with any + * subsequent load of the returned pmd_t *ret (ret is data dependent on *dir). + * + * If this ordering is not enforced, the CPU might load an older value of + * *ret, which may be uninitialized data. See mm/memory.c:__pte_alloc for + * more details. + * + * Note that we never change the mm->pgd pointer after the task is running, so + * pgd_offset does not require such a barrier. + */ + /* Find an entry in the second-level page table.. */ extern inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address) { - return (pmd_t *) pgd_page_vaddr(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PAGE - 1)); + pmd_t *ret = (pmd_t *) pgd_page_vaddr(*dir) + ((address >> PMD_SHIFT) & (PTRS_PER_PAGE - 1)); + smp_read_barrier_depends(); /* see above */ + return ret; } /* Find an entry in the third-level page table.. */ extern inline pte_t * pte_offset_kernel(pmd_t * dir, unsigned long address) { - return (pte_t *) pmd_page_vaddr(*dir) + pte_t *ret = (pte_t *) pmd_page_vaddr(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PAGE - 1)); + smp_read_barrier_depends(); /* see above */ + return ret; } #define pte_offset_map(dir,addr) pte_offset_kernel((dir),(addr)) diff --git a/mm/memory.c b/mm/memory.c index 48c122d4..fb5608a 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -311,6 +311,21 @@ int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address) if (!new) return -ENOMEM; + /* + * Ensure all pte setup (eg. pte page lock and page clearing) are + * visible before the pte is made visible to other CPUs by being + * put into page tables. + * + * The other side of the story is the pointer chasing in the page + * table walking code (when walking the page table without locking; + * ie. most of the time). Fortunately, these data accesses consist + * of a chain of data-dependent loads, meaning most CPUs (alpha + * being the notable exception) will already guarantee loads are + * seen in-order. See the alpha page table accessors for the + * smp_read_barrier_depends() barriers in page table walking code. + */ + smp_wmb(); /* Could be smp_wmb__xxx(before|after)_spin_lock */ + spin_lock(&mm->page_table_lock); if (!pmd_present(*pmd)) { /* Has another populated it ? */ mm->nr_ptes++; @@ -329,6 +344,8 @@ int __pte_alloc_kernel(pmd_t *pmd, unsigned long address) if (!new) return -ENOMEM; + smp_wmb(); /* See comment in __pte_alloc */ + spin_lock(&init_mm.page_table_lock); if (!pmd_present(*pmd)) { /* Has another populated it ? */ pmd_populate_kernel(&init_mm, pmd, new); @@ -2619,6 +2636,8 @@ int __pud_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address) if (!new) return -ENOMEM; + smp_wmb(); /* See comment in __pte_alloc */ + spin_lock(&mm->page_table_lock); if (pgd_present(*pgd)) /* Another has populated it */ pud_free(mm, new); @@ -2640,6 +2659,8 @@ int __pmd_alloc(struct mm_struct *mm, pud_t *pud, unsigned long address) if (!new) return -ENOMEM; + smp_wmb(); /* See comment in __pte_alloc */ + spin_lock(&mm->page_table_lock); #ifndef __ARCH_HAS_4LEVEL_HACK if (pud_present(*pud)) /* Another has populated it */ -- cgit v1.1 From 30f2f0eb4bd2c43d10a8b0d872c6e5ad8f31c9a0 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 6 May 2008 22:31:33 +0200 Subject: block: do_mounts - accept root= Some devices, like md, may create partitions only at first access, so allow root= to be set to a valid non-existant partition of an existing disk. This applies only to non-initramfs root mounting. This fixes a regression from 2.6.24 which did allow this to happen and broke some users machines :( Acked-by: Neil Brown Tested-by: Joao Luis Meloni Assirati Cc: stable Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- block/genhd.c | 9 ++++++--- include/linux/genhd.h | 4 ++-- init/do_mounts.c | 27 ++++++++++++++++++++++++++- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/block/genhd.c b/block/genhd.c index fda9c7a..129ad93 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -653,7 +653,7 @@ void genhd_media_change_notify(struct gendisk *disk) EXPORT_SYMBOL_GPL(genhd_media_change_notify); #endif /* 0 */ -dev_t blk_lookup_devt(const char *name) +dev_t blk_lookup_devt(const char *name, int part) { struct device *dev; dev_t devt = MKDEV(0, 0); @@ -661,7 +661,11 @@ dev_t blk_lookup_devt(const char *name) mutex_lock(&block_class_lock); list_for_each_entry(dev, &block_class.devices, node) { if (strcmp(dev->bus_id, name) == 0) { - devt = dev->devt; + struct gendisk *disk = dev_to_disk(dev); + + if (part < disk->minors) + devt = MKDEV(MAJOR(dev->devt), + MINOR(dev->devt) + part); break; } } @@ -669,7 +673,6 @@ dev_t blk_lookup_devt(const char *name) return devt; } - EXPORT_SYMBOL(blk_lookup_devt); struct gendisk *alloc_disk(int minors) diff --git a/include/linux/genhd.h b/include/linux/genhd.h index e9874e7..ae7aec3 100644 --- a/include/linux/genhd.h +++ b/include/linux/genhd.h @@ -525,7 +525,7 @@ struct unixware_disklabel { #define ADDPART_FLAG_RAID 1 #define ADDPART_FLAG_WHOLEDISK 2 -extern dev_t blk_lookup_devt(const char *name); +extern dev_t blk_lookup_devt(const char *name, int part); extern char *disk_name (struct gendisk *hd, int part, char *buf); extern int rescan_partitions(struct gendisk *disk, struct block_device *bdev); @@ -553,7 +553,7 @@ static inline struct block_device *bdget_disk(struct gendisk *disk, int index) static inline void printk_all_partitions(void) { } -static inline dev_t blk_lookup_devt(const char *name) +static inline dev_t blk_lookup_devt(const char *name, int part) { dev_t devt = MKDEV(0, 0); return devt; diff --git a/init/do_mounts.c b/init/do_mounts.c index 3885e70..660c1e5 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -76,6 +76,7 @@ dev_t name_to_dev_t(char *name) char s[32]; char *p; dev_t res = 0; + int part; if (strncmp(name, "/dev/", 5) != 0) { unsigned maj, min; @@ -106,7 +107,31 @@ dev_t name_to_dev_t(char *name) for (p = s; *p; p++) if (*p == '/') *p = '!'; - res = blk_lookup_devt(s); + res = blk_lookup_devt(s, 0); + if (res) + goto done; + + /* + * try non-existant, but valid partition, which may only exist + * after revalidating the disk, like partitioned md devices + */ + while (p > s && isdigit(p[-1])) + p--; + if (p == s || !*p || *p == '0') + goto fail; + + /* try disk name without */ + part = simple_strtoul(p, NULL, 10); + *p = '\0'; + res = blk_lookup_devt(s, part); + if (res) + goto done; + + /* try disk name without p */ + if (p < s + 2 || !isdigit(p[-2]) || p[-1] != 'p') + goto fail; + p[-1] = '\0'; + res = blk_lookup_devt(s, part); if (res) goto done; -- cgit v1.1 From 0a3ad00ca09632c6d0675f606276e92bdf1b306c Mon Sep 17 00:00:00 2001 From: Dave Young Date: Fri, 9 May 2008 15:24:08 +0800 Subject: Driver core: struct class remove children list because of the class_device was removed, now do the children list removing Signed-off-by: Dave Young Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 1 - include/linux/device.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/base/class.c b/drivers/base/class.c index 0ef00e8..e085af0 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -140,7 +140,6 @@ int class_register(struct class *cls) pr_debug("device class '%s': registering\n", cls->name); - INIT_LIST_HEAD(&cls->children); INIT_LIST_HEAD(&cls->devices); INIT_LIST_HEAD(&cls->interfaces); kset_init(&cls->class_dirs); diff --git a/include/linux/device.h b/include/linux/device.h index 8c23e3d..15e9fa3 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -183,7 +183,6 @@ struct class { struct module *owner; struct kset subsys; - struct list_head children; struct list_head devices; struct list_head interfaces; struct kset class_dirs; -- cgit v1.1 From 4d4423caaa1b9ca709ef6a911a030a3b6e68c46b Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Wed, 14 May 2008 23:06:14 +0200 Subject: SWARM IDE: Fix up following changes to ide_hwif_t Following recent changes to ide_hwif_t update the SWARM IDE driver to use hw_regs_t to initialize port mapping. Plus minor layout adjustments along the lines of other drivers. Signed-off-by: Maciej W. Rozycki Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/mips/swarm.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/ide/mips/swarm.c b/drivers/ide/mips/swarm.c index 712d17b..52fee3d 100644 --- a/drivers/ide/mips/swarm.c +++ b/drivers/ide/mips/swarm.c @@ -4,7 +4,7 @@ * Author: Manish Lachwani, mlachwani@mvista.com * Copyright (C) 2004 MIPS Technologies, Inc. All rights reserved. * Author: Maciej W. Rozycki - * Copyright (c) 2006 Maciej W. Rozycki + * Copyright (c) 2006, 2008 Maciej W. Rozycki * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -70,8 +70,9 @@ static int __devinit swarm_ide_probe(struct device *dev) ide_hwif_t *hwif; u8 __iomem *base; phys_t offset, size; + hw_regs_t hw; int i; - u8 idx[4] = { 0xff, 0xff, 0xff, 0xff }; + u8 idx[] = { 0xff, 0xff, 0xff, 0xff }; if (!SIBYTE_HAVE_IDE) return -ENODEV; @@ -112,14 +113,15 @@ static int __devinit swarm_ide_probe(struct device *dev) hwif->host_flags = IDE_HFLAG_MMIO; default_hwif_mmiops(hwif); - hwif->chipset = ide_generic; - for (i = 0; i <= 7; i++) - hwif->io_ports_array[i] = + hw.io_ports_array[i] = (unsigned long)(base + ((0x1f0 + i) << 5)); - hwif->io_ports.ctl_addr = + hw.io_ports.ctl_addr = (unsigned long)(base + (0x3f6 << 5)); - hwif->irq = K_INT_GB_IDE; + hw.irq = K_INT_GB_IDE; + hw.chipset = ide_generic; + + ide_init_port_hw(hwif, &hw); idx[0] = hwif->index; -- cgit v1.1 From e0b4eb5193fed5c63413b0c137be29b0477d15ca Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Wed, 14 May 2008 23:06:15 +0200 Subject: make ide-iops.c:SELECT_MASK() static SELECT_MASK() can now become static. [bart: remove space between function name and open parenthesis] Signed-off-by: Adrian Bunk Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 2 +- include/linux/ide.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 57d9a9a..0daf923 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -95,7 +95,7 @@ void SELECT_DRIVE (ide_drive_t *drive) hwif->OUTB(drive->select.all, hwif->io_ports.device_addr); } -void SELECT_MASK (ide_drive_t *drive, int mask) +static void SELECT_MASK(ide_drive_t *drive, int mask) { const struct ide_port_ops *port_ops = drive->hwif->port_ops; diff --git a/include/linux/ide.h b/include/linux/ide.h index b0135b0..19ec852 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -965,7 +965,6 @@ typedef struct ide_task_s { void ide_tf_dump(const char *, struct ide_taskfile *); extern void SELECT_DRIVE(ide_drive_t *); -extern void SELECT_MASK(ide_drive_t *, int); extern int drive_is_ready(ide_drive_t *); -- cgit v1.1 From df98668f178c39c54bc7b9cd3adb99cbd7ed8ada Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 14 May 2008 23:06:15 +0200 Subject: alim15x3: trivial cleanup for ali_set_pio_mode() Remove commented out code and stale comment. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/alim15x3.c | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index c1922f9..a23b975 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -76,11 +76,6 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio) a_clc = 0; c_time = ide_pio_timings[pio].cycle_time; -#if 0 - if ((r_clc = ((c_time - s_time - a_time) * bus_speed + 999) / 1000) >= 16) - r_clc = 0; -#endif - if (!(r_clc = (c_time * bus_speed + 999) / 1000 - a_clc - s_clc)) { r_clc = 1; } else { @@ -110,16 +105,6 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio) pci_write_config_byte(dev, port, s_clc); pci_write_config_byte(dev, port+drive->select.b.unit+2, (a_clc << 4) | r_clc); local_irq_restore(flags); - - /* - * setup active rec - * { 70, 165, 365 }, PIO Mode 0 - * { 50, 125, 208 }, PIO Mode 1 - * { 30, 100, 110 }, PIO Mode 2 - * { 30, 80, 70 }, PIO Mode 3 with IORDY - * { 25, 70, 25 }, PIO Mode 4 with IORDY ns - * { 20, 50, 30 } PIO Mode 5 with IORDY (nonstandard) - */ } /** -- cgit v1.1 From 2bf111d97a8c05d3fe436caaf18ba0634c9ab33d Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 14 May 2008 23:06:16 +0200 Subject: alim15x3: remove stale warning about ATI RS100 northbridge Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/alim15x3.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index a23b975..98ecf14 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -522,17 +522,9 @@ static const struct ide_port_info ali15x3_chipset __devinitdata = { static int __devinit alim15x3_init_one(struct pci_dev *dev, const struct pci_device_id *id) { - static struct pci_device_id ati_rs100[] = { - { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_RS100) }, - { }, - }; - struct ide_port_info d = ali15x3_chipset; u8 rev = dev->revision, idx = id->driver_data; - if (pci_dev_present(ati_rs100)) - printk(KERN_WARNING "alim15x3: ATI Radeon IGP Northbridge is not yet fully tested.\n"); - /* don't use LBA48 DMA on ALi devices before rev 0xC5 */ if (rev <= 0xC4) d.host_flags |= IDE_HFLAG_NO_LBA48_DMA; -- cgit v1.1 From 63b1623ef0e33160d782fd1b0044e9a8af5d16cf Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 14 May 2008 23:06:16 +0200 Subject: alim15x3: add "wdc_udma" module parameter Add "wdc_udma" module parameter for allowing UDMA transfers on M1543C-E chipset for WDC disks. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/alim15x3.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index 98ecf14..3eaab54 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -39,6 +39,16 @@ #include /* + * Allow UDMA on M1543C-E chipset for WDC disks that ignore CRC checking + * (this is DANGEROUS and could result in data corruption). + */ +static int wdc_udma; + +module_param(wdc_udma, bool, 0); +MODULE_PARM_DESC(wdc_udma, + "allow UDMA on M1543C-E chipset for WDC disks (DANGEROUS)"); + +/* * ALi devices are not plug in. Otherwise these static values would * need to go. They ought to go away anyway */ @@ -116,7 +126,7 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio) * The actual rules for the ALi are: * No UDMA on revisions <= 0x20 * Disk only for revisions < 0xC2 - * Not WDC drives for revisions < 0xC2 + * Not WDC drives on M1543C-E (?) * * FIXME: WDC ifdef needs to die */ @@ -127,7 +137,8 @@ static u8 ali_udma_filter(ide_drive_t *drive) if (drive->media != ide_disk) return 0; #ifndef CONFIG_WDC_ALI15X3 - if (chip_is_1543c_e && strstr(drive->id->model, "WDC ")) + if (chip_is_1543c_e && strstr(drive->id->model, "WDC ") && + wdc_udma == 0) return 0; #endif } -- cgit v1.1 From e7f379d5cabb2790ecce5d623382fa6085e7686d Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 14 May 2008 23:06:16 +0200 Subject: alim15x3: remove WDC_ALI15X3 config option There is "wdc_udma" module parameter now. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Kconfig | 15 --------------- drivers/ide/pci/alim15x3.c | 4 ---- 2 files changed, 19 deletions(-) diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index f702f91..627f08e 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -463,21 +463,6 @@ config BLK_DEV_ALI15X3 If unsure, say N. -config WDC_ALI15X3 - bool "ALI M15x3 WDC support (DANGEROUS)" - depends on BLK_DEV_ALI15X3 - ---help--- - This allows for UltraDMA support for WDC drives that ignore CRC - checking. You are a fool for enabling this option, but there have - been requests. DO NOT COMPLAIN IF YOUR DRIVE HAS FS CORRUPTION, IF - YOU ENABLE THIS! No one will listen, just laugh for ignoring this - SERIOUS WARNING. - - Using this option can allow WDC drives to run at ATA-4/5 transfer - rates with only an ATA-2 support structure. - - SAY N! - config BLK_DEV_AMD74XX tristate "AMD and nVidia IDE support" depends on !ARM diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index 3eaab54..f2129d5 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c @@ -127,8 +127,6 @@ static void ali_set_pio_mode(ide_drive_t *drive, const u8 pio) * No UDMA on revisions <= 0x20 * Disk only for revisions < 0xC2 * Not WDC drives on M1543C-E (?) - * - * FIXME: WDC ifdef needs to die */ static u8 ali_udma_filter(ide_drive_t *drive) @@ -136,11 +134,9 @@ static u8 ali_udma_filter(ide_drive_t *drive) if (m5229_revision > 0x20 && m5229_revision < 0xC2) { if (drive->media != ide_disk) return 0; -#ifndef CONFIG_WDC_ALI15X3 if (chip_is_1543c_e && strstr(drive->id->model, "WDC ") && wdc_udma == 0) return 0; -#endif } return drive->hwif->ultra_mask; -- cgit v1.1 From 64afc31f8976bda66e82a41aacb1f7e427fb179e Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 14 May 2008 23:06:16 +0200 Subject: ide/Kconfig: couple of fixes * Don't ask to enable no longer existing config options ("Use DMA by default when available" and "Special UDMA Feature"). * PIIX host driver doesn't support Victory66 chipset. * "ide0=cmd640_vlb" -> "cmd640.probe_vlb" * "ide=doubler" -> "gayle.doubler" * Amiga IDE doubler support is a feature for gayle host driver not a separate host driver. * Remove Andre's mail. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Kconfig | 39 +++++++++++---------------------------- 1 file changed, 11 insertions(+), 28 deletions(-) diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 627f08e..b4f3aef 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -1,8 +1,6 @@ # # IDE ATA ATAPI Block device driver configuration # -# Andre Hedrick -# # Select HAVE_IDE if IDE is supported config HAVE_IDE @@ -335,7 +333,7 @@ config BLK_DEV_CMD640 This driver will work automatically in PCI based systems (most new systems have PCI slots). But if your system uses VESA local bus (VLB) instead of PCI, you must also supply a kernel boot parameter - to enable the CMD640 bugfix/support: "ide0=cmd640_vlb". (Try "man + to enable the CMD640 bugfix/support: "cmd640.probe_vlb". (Try "man bootparam" or see the documentation of your boot loader about how to pass options to the kernel.) @@ -457,8 +455,7 @@ config BLK_DEV_ALI15X3 onboard chipsets. It also tests for Simplex mode and enables normal dual channel support. - If you say Y here, you also need to say Y to "Use DMA by default - when available", above. Please read the comments at the top of + Please read the comments at the top of . If unsure, say N. @@ -505,9 +502,6 @@ config BLK_DEV_CY82C693 This driver adds detection and support for the CY82C693 chipset used on Digital's PC-Alpha 164SX boards. - If you say Y here, you need to say Y to "Use DMA by default - when available" as well. - config BLK_DEV_CS5520 tristate "Cyrix CS5510/20 MediaGX chipset support (VERY EXPERIMENTAL)" depends on EXPERIMENTAL @@ -598,13 +592,12 @@ config BLK_DEV_SC1200 National SCx200 series of embedded x86 "Geode" systems. config BLK_DEV_PIIX - tristate "Intel PIIXn chipsets support" + tristate "Intel PIIX/ICH chipsets support" select BLK_DEV_IDEDMA_PCI help - This driver adds explicit support for Intel PIIX and ICH chips - and also for the Efar Victory66 (slc90e66) chip. This allows - the kernel to change PIO, DMA and UDMA speeds and to configure - the chip to optimum performance. + This driver adds explicit support for Intel PIIX and ICH chips. + This allows the kernel to change PIO, DMA and UDMA speeds and to + configure the chip to optimum performance. config BLK_DEV_IT8213 tristate "IT8213 IDE support" @@ -642,11 +635,7 @@ config BLK_DEV_PDC202XX_OLD happen if the BIOS revisions of all installed cards (three-max) do not match, the driver attempts to do dynamic tuning of the chipset at boot-time for max-speed. Ultra33 BIOS 1.25 or newer is required - for more than one card. This card may require that you say Y to - "Special UDMA Feature". - - If you say Y here, you need to say Y to "Use DMA by default when - available" as well. + for more than one card. Please read the comments at the top of . @@ -695,9 +684,6 @@ config BLK_DEV_SIS5513 ATA100: SiS635, SiS645, SiS650, SiS730, SiS735, SiS740, SiS745, SiS750 - If you say Y here, you need to say Y to "Use DMA by default when - available" as well. - Please read the comments at the top of . config BLK_DEV_SL82C105 @@ -719,9 +705,6 @@ config BLK_DEV_SLC90E66 and it will handle timing cycles. Since this is an improved look-a-like to the PIIX4 it should be a nice addition. - If you say Y here, you need to say Y to "Use DMA by default when - available" as well. - Please read the comments at the top of . @@ -873,17 +856,17 @@ config BLK_DEV_IDEDOUBLER bool "Amiga IDE Doubler support (EXPERIMENTAL)" depends on BLK_DEV_GAYLE && EXPERIMENTAL ---help--- - This driver provides support for the so-called `IDE doublers' (made + This feature provides support for the so-called `IDE doublers' (made by various manufacturers, e.g. Eyetech) that can be connected to the on-board IDE interface of some Amiga models. Using such an IDE doubler, you can connect up to four instead of two IDE devices to the Amiga's on-board IDE interface. Note that the normal Amiga Gayle IDE driver may not work correctly - if you have an IDE doubler and don't enable this driver! + if you have an IDE doubler and don't enable this feature! - Say Y if you have an IDE doubler. The driver is enabled at kernel - runtime using the "ide=doubler" kernel boot parameter. + Say Y if you have an IDE doubler. The feature is enabled at kernel + runtime using the "gayle.doubler" kernel boot parameter. config BLK_DEV_BUDDHA tristate "Buddha/Catweasel/X-Surf IDE interface support (EXPERIMENTAL)" -- cgit v1.1 From cafa027b8cc6f605ccebc43a960644307a12d8dd Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Wed, 14 May 2008 23:06:16 +0200 Subject: cs5520: disable VDMA Disable Virtual DMA support for now (it causes system hangs). Thanks to TAKADA Yoshihito for the help with debugging the problem. Reported-by: TAKADA Yoshihito Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/cs5520.c | 2 +- include/linux/ide.h | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/ide/pci/cs5520.c b/drivers/ide/pci/cs5520.c index 17669a4..992b1cf 100644 --- a/drivers/ide/pci/cs5520.c +++ b/drivers/ide/pci/cs5520.c @@ -119,6 +119,7 @@ static const struct ide_dma_ops cs5520_dma_ops = { .dma_timeout = ide_dma_timeout, }; +/* FIXME: VDMA is disabled because it caused system hangs */ #define DECLARE_CS_DEV(name_str) \ { \ .name = name_str, \ @@ -126,7 +127,6 @@ static const struct ide_dma_ops cs5520_dma_ops = { .dma_ops = &cs5520_dma_ops, \ .host_flags = IDE_HFLAG_ISA_PORTS | \ IDE_HFLAG_CS5520 | \ - IDE_HFLAG_VDMA | \ IDE_HFLAG_NO_ATAPI_DMA | \ IDE_HFLAG_ABUSE_SET_DMA_MODE, \ .pio_mask = ATA_PIO4, \ diff --git a/include/linux/ide.h b/include/linux/ide.h index 19ec852..f8f195c 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1057,8 +1057,8 @@ enum { IDE_HFLAG_NO_SET_MODE = (1 << 9), /* trust BIOS for programming chipset/device for DMA */ IDE_HFLAG_TRUST_BIOS_FOR_DMA = (1 << 10), - /* host uses VDMA (tied with IDE_HFLAG_CS5520 for now) */ - IDE_HFLAG_VDMA = (1 << 11), + /* host is CS5510/CS5520 */ + IDE_HFLAG_CS5520 = (1 << 11), /* ATAPI DMA is unsupported */ IDE_HFLAG_NO_ATAPI_DMA = (1 << 12), /* set if host is a "non-bootable" controller */ @@ -1069,8 +1069,6 @@ enum { IDE_HFLAG_NO_AUTODMA = (1 << 15), /* host uses MMIO */ IDE_HFLAG_MMIO = (1 << 16), - /* host is CS5510/CS5520 */ - IDE_HFLAG_CS5520 = IDE_HFLAG_VDMA, /* no LBA48 */ IDE_HFLAG_NO_LBA48 = (1 << 17), /* no LBA48 DMA */ @@ -1100,6 +1098,8 @@ enum { IDE_HFLAG_NO_IO_32BIT = (1 << 30), /* never unmask IRQs */ IDE_HFLAG_NO_UNMASK_IRQS = (1 << 31), + /* host uses VDMA (disabled for now) */ + IDE_HFLAG_VDMA = 0, }; #ifdef CONFIG_BLK_DEV_OFFBOARD -- cgit v1.1 From 7868f1ed84696d3cca83558e8dd459f20a36d077 Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Tue, 6 May 2008 15:18:55 -0500 Subject: [IA64] Add header files for SGI UV platform Add new UV-specific header files. Signed-off-by: Jack Steiner Signed-off-by: Tony Luck --- include/asm-ia64/uv/uv_hub.h | 309 ++++++++++++++++++++++++++++++++++++++++++ include/asm-ia64/uv/uv_mmrs.h | 266 ++++++++++++++++++++++++++++++++++++ 2 files changed, 575 insertions(+) create mode 100644 include/asm-ia64/uv/uv_hub.h create mode 100644 include/asm-ia64/uv/uv_mmrs.h diff --git a/include/asm-ia64/uv/uv_hub.h b/include/asm-ia64/uv/uv_hub.h new file mode 100644 index 0000000..f607018 --- /dev/null +++ b/include/asm-ia64/uv/uv_hub.h @@ -0,0 +1,309 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * SGI UV architectural definitions + * + * Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved. + */ + +#ifndef __ASM_IA64_UV_HUB_H__ +#define __ASM_IA64_UV_HUB_H__ + +#include +#include +#include +#include + + +/* + * Addressing Terminology + * + * M - The low M bits of a physical address represent the offset + * into the blade local memory. RAM memory on a blade is physically + * contiguous (although various IO spaces may punch holes in + * it).. + * + * N - Number of bits in the node portion of a socket physical + * address. + * + * NASID - network ID of a router, Mbrick or Cbrick. Nasid values of + * routers always have low bit of 1, C/MBricks have low bit + * equal to 0. Most addressing macros that target UV hub chips + * right shift the NASID by 1 to exclude the always-zero bit. + * NASIDs contain up to 15 bits. + * + * GNODE - NASID right shifted by 1 bit. Most mmrs contain gnodes instead + * of nasids. + * + * PNODE - the low N bits of the GNODE. The PNODE is the most useful variant + * of the nasid for socket usage. + * + * + * NumaLink Global Physical Address Format: + * +--------------------------------+---------------------+ + * |00..000| GNODE | NodeOffset | + * +--------------------------------+---------------------+ + * |<-------53 - M bits --->|<--------M bits -----> + * + * M - number of node offset bits (35 .. 40) + * + * + * Memory/UV-HUB Processor Socket Address Format: + * +----------------+---------------+---------------------+ + * |00..000000000000| PNODE | NodeOffset | + * +----------------+---------------+---------------------+ + * <--- N bits --->|<--------M bits -----> + * + * M - number of node offset bits (35 .. 40) + * N - number of PNODE bits (0 .. 10) + * + * Note: M + N cannot currently exceed 44 (x86_64) or 46 (IA64). + * The actual values are configuration dependent and are set at + * boot time. M & N values are set by the hardware/BIOS at boot. + */ + + +/* + * Maximum number of bricks in all partitions and in all coherency domains. + * This is the total number of bricks accessible in the numalink fabric. It + * includes all C & M bricks. Routers are NOT included. + * + * This value is also the value of the maximum number of non-router NASIDs + * in the numalink fabric. + * + * NOTE: a brick may contain 1 or 2 OS nodes. Don't get these confused. + */ +#define UV_MAX_NUMALINK_BLADES 16384 + +/* + * Maximum number of C/Mbricks within a software SSI (hardware may support + * more). + */ +#define UV_MAX_SSI_BLADES 1 + +/* + * The largest possible NASID of a C or M brick (+ 2) + */ +#define UV_MAX_NASID_VALUE (UV_MAX_NUMALINK_NODES * 2) + +/* + * The following defines attributes of the HUB chip. These attributes are + * frequently referenced and are kept in the per-cpu data areas of each cpu. + * They are kept together in a struct to minimize cache misses. + */ +struct uv_hub_info_s { + unsigned long global_mmr_base; + unsigned long gpa_mask; + unsigned long gnode_upper; + unsigned long lowmem_remap_top; + unsigned long lowmem_remap_base; + unsigned short pnode; + unsigned short pnode_mask; + unsigned short coherency_domain_number; + unsigned short numa_blade_id; + unsigned char blade_processor_id; + unsigned char m_val; + unsigned char n_val; +}; +DECLARE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); +#define uv_hub_info (&__get_cpu_var(__uv_hub_info)) +#define uv_cpu_hub_info(cpu) (&per_cpu(__uv_hub_info, cpu)) + +/* + * Local & Global MMR space macros. + * Note: macros are intended to be used ONLY by inline functions + * in this file - not by other kernel code. + * n - NASID (full 15-bit global nasid) + * g - GNODE (full 15-bit global nasid, right shifted 1) + * p - PNODE (local part of nsids, right shifted 1) + */ +#define UV_NASID_TO_PNODE(n) (((n) >> 1) & uv_hub_info->pnode_mask) +#define UV_PNODE_TO_NASID(p) (((p) << 1) | uv_hub_info->gnode_upper) + +#define UV_LOCAL_MMR_BASE 0xf4000000UL +#define UV_GLOBAL_MMR32_BASE 0xf8000000UL +#define UV_GLOBAL_MMR64_BASE (uv_hub_info->global_mmr_base) + +#define UV_GLOBAL_MMR32_PNODE_SHIFT 15 +#define UV_GLOBAL_MMR64_PNODE_SHIFT 26 + +#define UV_GLOBAL_MMR32_PNODE_BITS(p) ((p) << (UV_GLOBAL_MMR32_PNODE_SHIFT)) + +#define UV_GLOBAL_MMR64_PNODE_BITS(p) \ + ((unsigned long)(p) << UV_GLOBAL_MMR64_PNODE_SHIFT) + +/* + * Macros for converting between kernel virtual addresses, socket local physical + * addresses, and UV global physical addresses. + * Note: use the standard __pa() & __va() macros for converting + * between socket virtual and socket physical addresses. + */ + +/* socket phys RAM --> UV global physical address */ +static inline unsigned long uv_soc_phys_ram_to_gpa(unsigned long paddr) +{ + if (paddr < uv_hub_info->lowmem_remap_top) + paddr += uv_hub_info->lowmem_remap_base; + return paddr | uv_hub_info->gnode_upper; +} + + +/* socket virtual --> UV global physical address */ +static inline unsigned long uv_gpa(void *v) +{ + return __pa(v) | uv_hub_info->gnode_upper; +} + +/* socket virtual --> UV global physical address */ +static inline void *uv_vgpa(void *v) +{ + return (void *)uv_gpa(v); +} + +/* UV global physical address --> socket virtual */ +static inline void *uv_va(unsigned long gpa) +{ + return __va(gpa & uv_hub_info->gpa_mask); +} + +/* pnode, offset --> socket virtual */ +static inline void *uv_pnode_offset_to_vaddr(int pnode, unsigned long offset) +{ + return __va(((unsigned long)pnode << uv_hub_info->m_val) | offset); +} + + +/* + * Access global MMRs using the low memory MMR32 space. This region supports + * faster MMR access but not all MMRs are accessible in this space. + */ +static inline unsigned long *uv_global_mmr32_address(int pnode, + unsigned long offset) +{ + return __va(UV_GLOBAL_MMR32_BASE | + UV_GLOBAL_MMR32_PNODE_BITS(pnode) | offset); +} + +static inline void uv_write_global_mmr32(int pnode, unsigned long offset, + unsigned long val) +{ + *uv_global_mmr32_address(pnode, offset) = val; +} + +static inline unsigned long uv_read_global_mmr32(int pnode, + unsigned long offset) +{ + return *uv_global_mmr32_address(pnode, offset); +} + +/* + * Access Global MMR space using the MMR space located at the top of physical + * memory. + */ +static inline unsigned long *uv_global_mmr64_address(int pnode, + unsigned long offset) +{ + return __va(UV_GLOBAL_MMR64_BASE | + UV_GLOBAL_MMR64_PNODE_BITS(pnode) | offset); +} + +static inline void uv_write_global_mmr64(int pnode, unsigned long offset, + unsigned long val) +{ + *uv_global_mmr64_address(pnode, offset) = val; +} + +static inline unsigned long uv_read_global_mmr64(int pnode, + unsigned long offset) +{ + return *uv_global_mmr64_address(pnode, offset); +} + +/* + * Access hub local MMRs. Faster than using global space but only local MMRs + * are accessible. + */ +static inline unsigned long *uv_local_mmr_address(unsigned long offset) +{ + return __va(UV_LOCAL_MMR_BASE | offset); +} + +static inline unsigned long uv_read_local_mmr(unsigned long offset) +{ + return *uv_local_mmr_address(offset); +} + +static inline void uv_write_local_mmr(unsigned long offset, unsigned long val) +{ + *uv_local_mmr_address(offset) = val; +} + +/* + * Structures and definitions for converting between cpu, node, pnode, and blade + * numbers. + */ + +/* Blade-local cpu number of current cpu. Numbered 0 .. <# cpus on the blade> */ +static inline int uv_blade_processor_id(void) +{ + return smp_processor_id(); +} + +/* Blade number of current cpu. Numnbered 0 .. <#blades -1> */ +static inline int uv_numa_blade_id(void) +{ + return 0; +} + +/* Convert a cpu number to the the UV blade number */ +static inline int uv_cpu_to_blade_id(int cpu) +{ + return 0; +} + +/* Convert linux node number to the UV blade number */ +static inline int uv_node_to_blade_id(int nid) +{ + return 0; +} + +/* Convert a blade id to the PNODE of the blade */ +static inline int uv_blade_to_pnode(int bid) +{ + return 0; +} + +/* Determine the number of possible cpus on a blade */ +static inline int uv_blade_nr_possible_cpus(int bid) +{ + return num_possible_cpus(); +} + +/* Determine the number of online cpus on a blade */ +static inline int uv_blade_nr_online_cpus(int bid) +{ + return num_online_cpus(); +} + +/* Convert a cpu id to the PNODE of the blade containing the cpu */ +static inline int uv_cpu_to_pnode(int cpu) +{ + return 0; +} + +/* Convert a linux node number to the PNODE of the blade */ +static inline int uv_node_to_pnode(int nid) +{ + return 0; +} + +/* Maximum possible number of blades */ +static inline int uv_num_possible_blades(void) +{ + return 1; +} + +#endif /* __ASM_IA64_UV_HUB__ */ + diff --git a/include/asm-ia64/uv/uv_mmrs.h b/include/asm-ia64/uv/uv_mmrs.h new file mode 100644 index 0000000..1cc1dbb --- /dev/null +++ b/include/asm-ia64/uv/uv_mmrs.h @@ -0,0 +1,266 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * SGI UV MMR definitions + * + * Copyright (C) 2007-2008 Silicon Graphics, Inc. All rights reserved. + */ + +#ifndef __ASM_IA64_UV_MMRS__ +#define __ASM_IA64_UV_MMRS__ + +/* + * AUTO GENERATED - Do not edit + */ + + #define UV_MMR_ENABLE (1UL << 63) + +/* ========================================================================= */ +/* UVH_NODE_ID */ +/* ========================================================================= */ +#define UVH_NODE_ID 0x0UL + +#define UVH_NODE_ID_FORCE1_SHFT 0 +#define UVH_NODE_ID_FORCE1_MASK 0x0000000000000001UL +#define UVH_NODE_ID_MANUFACTURER_SHFT 1 +#define UVH_NODE_ID_MANUFACTURER_MASK 0x0000000000000ffeUL +#define UVH_NODE_ID_PART_NUMBER_SHFT 12 +#define UVH_NODE_ID_PART_NUMBER_MASK 0x000000000ffff000UL +#define UVH_NODE_ID_REVISION_SHFT 28 +#define UVH_NODE_ID_REVISION_MASK 0x00000000f0000000UL +#define UVH_NODE_ID_NODE_ID_SHFT 32 +#define UVH_NODE_ID_NODE_ID_MASK 0x00007fff00000000UL +#define UVH_NODE_ID_NODES_PER_BIT_SHFT 48 +#define UVH_NODE_ID_NODES_PER_BIT_MASK 0x007f000000000000UL +#define UVH_NODE_ID_NI_PORT_SHFT 56 +#define UVH_NODE_ID_NI_PORT_MASK 0x0f00000000000000UL + +union uvh_node_id_u { + unsigned long v; + struct uvh_node_id_s { + unsigned long force1 : 1; /* RO */ + unsigned long manufacturer : 11; /* RO */ + unsigned long part_number : 16; /* RO */ + unsigned long revision : 4; /* RO */ + unsigned long node_id : 15; /* RW */ + unsigned long rsvd_47 : 1; /* */ + unsigned long nodes_per_bit : 7; /* RW */ + unsigned long rsvd_55 : 1; /* */ + unsigned long ni_port : 4; /* RO */ + unsigned long rsvd_60_63 : 4; /* */ + } s; +}; + +/* ========================================================================= */ +/* UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR */ +/* ========================================================================= */ +#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR 0x16000d0UL + +#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_SHFT 24 +#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_MASK 0x00003fffff000000UL + +union uvh_rh_gam_alias210_redirect_config_0_mmr_u { + unsigned long v; + struct uvh_rh_gam_alias210_redirect_config_0_mmr_s { + unsigned long rsvd_0_23 : 24; /* */ + unsigned long dest_base : 22; /* RW */ + unsigned long rsvd_46_63: 18; /* */ + } s; +}; + +/* ========================================================================= */ +/* UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR */ +/* ========================================================================= */ +#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR 0x16000e0UL + +#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR_DEST_BASE_SHFT 24 +#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR_DEST_BASE_MASK 0x00003fffff000000UL + +union uvh_rh_gam_alias210_redirect_config_1_mmr_u { + unsigned long v; + struct uvh_rh_gam_alias210_redirect_config_1_mmr_s { + unsigned long rsvd_0_23 : 24; /* */ + unsigned long dest_base : 22; /* RW */ + unsigned long rsvd_46_63: 18; /* */ + } s; +}; + +/* ========================================================================= */ +/* UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR */ +/* ========================================================================= */ +#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR 0x16000f0UL + +#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR_DEST_BASE_SHFT 24 +#define UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR_DEST_BASE_MASK 0x00003fffff000000UL + +union uvh_rh_gam_alias210_redirect_config_2_mmr_u { + unsigned long v; + struct uvh_rh_gam_alias210_redirect_config_2_mmr_s { + unsigned long rsvd_0_23 : 24; /* */ + unsigned long dest_base : 22; /* RW */ + unsigned long rsvd_46_63: 18; /* */ + } s; +}; + +/* ========================================================================= */ +/* UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR */ +/* ========================================================================= */ +#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR 0x1600010UL + +#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_SHFT 28 +#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffff0000000UL +#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_SHFT 46 +#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_GR4_MASK 0x0000400000000000UL +#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_SHFT 52 +#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_N_GRU_MASK 0x00f0000000000000UL +#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63 +#define UVH_RH_GAM_GRU_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL + +union uvh_rh_gam_gru_overlay_config_mmr_u { + unsigned long v; + struct uvh_rh_gam_gru_overlay_config_mmr_s { + unsigned long rsvd_0_27: 28; /* */ + unsigned long base : 18; /* RW */ + unsigned long gr4 : 1; /* RW */ + unsigned long rsvd_47_51: 5; /* */ + unsigned long n_gru : 4; /* RW */ + unsigned long rsvd_56_62: 7; /* */ + unsigned long enable : 1; /* RW */ + } s; +}; + +/* ========================================================================= */ +/* UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR */ +/* ========================================================================= */ +#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR 0x1600028UL + +#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_SHFT 26 +#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_BASE_MASK 0x00003ffffc000000UL +#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_DUAL_HUB_SHFT 46 +#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_DUAL_HUB_MASK 0x0000400000000000UL +#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_SHFT 63 +#define UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR_ENABLE_MASK 0x8000000000000000UL + +union uvh_rh_gam_mmr_overlay_config_mmr_u { + unsigned long v; + struct uvh_rh_gam_mmr_overlay_config_mmr_s { + unsigned long rsvd_0_25: 26; /* */ + unsigned long base : 20; /* RW */ + unsigned long dual_hub : 1; /* RW */ + unsigned long rsvd_47_62: 16; /* */ + unsigned long enable : 1; /* RW */ + } s; +}; + +/* ========================================================================= */ +/* UVH_RTC */ +/* ========================================================================= */ +#define UVH_RTC 0x28000UL + +#define UVH_RTC_REAL_TIME_CLOCK_SHFT 0 +#define UVH_RTC_REAL_TIME_CLOCK_MASK 0x00ffffffffffffffUL + +union uvh_rtc_u { + unsigned long v; + struct uvh_rtc_s { + unsigned long real_time_clock : 56; /* RW */ + unsigned long rsvd_56_63 : 8; /* */ + } s; +}; + +/* ========================================================================= */ +/* UVH_SI_ADDR_MAP_CONFIG */ +/* ========================================================================= */ +#define UVH_SI_ADDR_MAP_CONFIG 0xc80000UL + +#define UVH_SI_ADDR_MAP_CONFIG_M_SKT_SHFT 0 +#define UVH_SI_ADDR_MAP_CONFIG_M_SKT_MASK 0x000000000000003fUL +#define UVH_SI_ADDR_MAP_CONFIG_N_SKT_SHFT 8 +#define UVH_SI_ADDR_MAP_CONFIG_N_SKT_MASK 0x0000000000000f00UL + +union uvh_si_addr_map_config_u { + unsigned long v; + struct uvh_si_addr_map_config_s { + unsigned long m_skt : 6; /* RW */ + unsigned long rsvd_6_7: 2; /* */ + unsigned long n_skt : 4; /* RW */ + unsigned long rsvd_12_63: 52; /* */ + } s; +}; + +/* ========================================================================= */ +/* UVH_SI_ALIAS0_OVERLAY_CONFIG */ +/* ========================================================================= */ +#define UVH_SI_ALIAS0_OVERLAY_CONFIG 0xc80008UL + +#define UVH_SI_ALIAS0_OVERLAY_CONFIG_BASE_SHFT 24 +#define UVH_SI_ALIAS0_OVERLAY_CONFIG_BASE_MASK 0x00000000ff000000UL +#define UVH_SI_ALIAS0_OVERLAY_CONFIG_M_ALIAS_SHFT 48 +#define UVH_SI_ALIAS0_OVERLAY_CONFIG_M_ALIAS_MASK 0x001f000000000000UL +#define UVH_SI_ALIAS0_OVERLAY_CONFIG_ENABLE_SHFT 63 +#define UVH_SI_ALIAS0_OVERLAY_CONFIG_ENABLE_MASK 0x8000000000000000UL + +union uvh_si_alias0_overlay_config_u { + unsigned long v; + struct uvh_si_alias0_overlay_config_s { + unsigned long rsvd_0_23: 24; /* */ + unsigned long base : 8; /* RW */ + unsigned long rsvd_32_47: 16; /* */ + unsigned long m_alias : 5; /* RW */ + unsigned long rsvd_53_62: 10; /* */ + unsigned long enable : 1; /* RW */ + } s; +}; + +/* ========================================================================= */ +/* UVH_SI_ALIAS1_OVERLAY_CONFIG */ +/* ========================================================================= */ +#define UVH_SI_ALIAS1_OVERLAY_CONFIG 0xc80010UL + +#define UVH_SI_ALIAS1_OVERLAY_CONFIG_BASE_SHFT 24 +#define UVH_SI_ALIAS1_OVERLAY_CONFIG_BASE_MASK 0x00000000ff000000UL +#define UVH_SI_ALIAS1_OVERLAY_CONFIG_M_ALIAS_SHFT 48 +#define UVH_SI_ALIAS1_OVERLAY_CONFIG_M_ALIAS_MASK 0x001f000000000000UL +#define UVH_SI_ALIAS1_OVERLAY_CONFIG_ENABLE_SHFT 63 +#define UVH_SI_ALIAS1_OVERLAY_CONFIG_ENABLE_MASK 0x8000000000000000UL + +union uvh_si_alias1_overlay_config_u { + unsigned long v; + struct uvh_si_alias1_overlay_config_s { + unsigned long rsvd_0_23: 24; /* */ + unsigned long base : 8; /* RW */ + unsigned long rsvd_32_47: 16; /* */ + unsigned long m_alias : 5; /* RW */ + unsigned long rsvd_53_62: 10; /* */ + unsigned long enable : 1; /* RW */ + } s; +}; + +/* ========================================================================= */ +/* UVH_SI_ALIAS2_OVERLAY_CONFIG */ +/* ========================================================================= */ +#define UVH_SI_ALIAS2_OVERLAY_CONFIG 0xc80018UL + +#define UVH_SI_ALIAS2_OVERLAY_CONFIG_BASE_SHFT 24 +#define UVH_SI_ALIAS2_OVERLAY_CONFIG_BASE_MASK 0x00000000ff000000UL +#define UVH_SI_ALIAS2_OVERLAY_CONFIG_M_ALIAS_SHFT 48 +#define UVH_SI_ALIAS2_OVERLAY_CONFIG_M_ALIAS_MASK 0x001f000000000000UL +#define UVH_SI_ALIAS2_OVERLAY_CONFIG_ENABLE_SHFT 63 +#define UVH_SI_ALIAS2_OVERLAY_CONFIG_ENABLE_MASK 0x8000000000000000UL + +union uvh_si_alias2_overlay_config_u { + unsigned long v; + struct uvh_si_alias2_overlay_config_s { + unsigned long rsvd_0_23: 24; /* */ + unsigned long base : 8; /* RW */ + unsigned long rsvd_32_47: 16; /* */ + unsigned long m_alias : 5; /* RW */ + unsigned long rsvd_53_62: 10; /* */ + unsigned long enable : 1; /* RW */ + } s; +}; + + +#endif /* __ASM_IA64_UV_MMRS__ */ -- cgit v1.1 From 2224661494278bfc1c35b392cf6ee6f58e1d5e64 Mon Sep 17 00:00:00 2001 From: Jack Steiner Date: Tue, 6 May 2008 15:18:57 -0500 Subject: [IA64] machvec support for SGI UV platform This patch adds the basic IA64 machvec infrastructure to support the SGI "UV" platform. Signed-off-by: Jack Steiner Signed-off-by: Tony Luck --- arch/ia64/Kconfig | 13 ++++++ arch/ia64/Makefile | 2 +- arch/ia64/kernel/acpi.c | 7 +++- arch/ia64/uv/Makefile | 12 ++++++ arch/ia64/uv/kernel/Makefile | 13 ++++++ arch/ia64/uv/kernel/machvec.c | 11 +++++ arch/ia64/uv/kernel/setup.c | 98 +++++++++++++++++++++++++++++++++++++++++++ include/asm-ia64/machvec.h | 2 + include/asm-ia64/machvec_uv.h | 26 ++++++++++++ 9 files changed, 182 insertions(+), 2 deletions(-) create mode 100644 arch/ia64/uv/Makefile create mode 100644 arch/ia64/uv/kernel/Makefile create mode 100644 arch/ia64/uv/kernel/machvec.c create mode 100644 arch/ia64/uv/kernel/setup.c create mode 100644 include/asm-ia64/machvec_uv.h diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 0df5f6f..16be414 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -135,6 +135,7 @@ config IA64_GENERIC HP-zx1/sx1000 For HP systems HP-zx1/sx1000+swiotlb For HP systems with (broken) DMA-constrained devices. SGI-SN2 For SGI Altix systems + SGI-UV For SGI UV systems Ski-simulator For the HP simulator If you don't know what to do, choose "generic". @@ -170,6 +171,18 @@ config IA64_SGI_SN2 to select this option. If in doubt, select ia64 generic support instead. +config IA64_SGI_UV` + bool "SGI-UV`" + select NUMA + select ACPI_NUMA + select SWIOTLB + help + Selecting this option will optimize the kernel for use on UV based + systems, but the resulting kernel binary will not run on other + types of ia64 systems. If you have an SGI UV system, it's safe + to select this option. If in doubt, select ia64 generic support + instead. + config IA64_HP_SIM bool "Ski-simulator" select SWIOTLB diff --git a/arch/ia64/Makefile b/arch/ia64/Makefile index ec4cca4..88f1a55 100644 --- a/arch/ia64/Makefile +++ b/arch/ia64/Makefile @@ -63,7 +63,7 @@ drivers-$(CONFIG_PCI) += arch/ia64/pci/ drivers-$(CONFIG_IA64_HP_SIM) += arch/ia64/hp/sim/ drivers-$(CONFIG_IA64_HP_ZX1) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ drivers-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ -drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ arch/ia64/sn/ +drivers-$(CONFIG_IA64_GENERIC) += arch/ia64/hp/common/ arch/ia64/hp/zx1/ arch/ia64/hp/sim/ arch/ia64/sn/ arch/ia64/uv/ drivers-$(CONFIG_OPROFILE) += arch/ia64/oprofile/ boot := arch/ia64/hp/sim/boot diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 19709a0..6ff6815 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -117,7 +117,10 @@ acpi_get_sysname(void) if (!strcmp(hdr->oem_id, "HP")) { return "hpzx1"; } else if (!strcmp(hdr->oem_id, "SGI")) { - return "sn2"; + if (!strcmp(hdr->oem_table_id + 4, "UV")) + return "uv"; + else + return "sn2"; } return "dig"; @@ -130,6 +133,8 @@ acpi_get_sysname(void) return "hpzx1_swiotlb"; # elif defined (CONFIG_IA64_SGI_SN2) return "sn2"; +# elif defined (CONFIG_IA64_SGI_UV) + return "uv"; # elif defined (CONFIG_IA64_DIG) return "dig"; # else diff --git a/arch/ia64/uv/Makefile b/arch/ia64/uv/Makefile new file mode 100644 index 0000000..aa9f919 --- /dev/null +++ b/arch/ia64/uv/Makefile @@ -0,0 +1,12 @@ +# arch/ia64/uv/Makefile +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 2008 Silicon Graphics, Inc. All Rights Reserved. +# +# Makefile for the sn uv subplatform +# + +obj-y += kernel/ diff --git a/arch/ia64/uv/kernel/Makefile b/arch/ia64/uv/kernel/Makefile new file mode 100644 index 0000000..8d92b46 --- /dev/null +++ b/arch/ia64/uv/kernel/Makefile @@ -0,0 +1,13 @@ +# arch/ia64/uv/kernel/Makefile +# +# This file is subject to the terms and conditions of the GNU General Public +# License. See the file "COPYING" in the main directory of this archive +# for more details. +# +# Copyright (C) 2008 Silicon Graphics, Inc. All Rights Reserved. +# + +EXTRA_CFLAGS += -Iarch/ia64/sn/include + +obj-y += setup.o +obj-$(CONFIG_IA64_GENERIC) += machvec.o diff --git a/arch/ia64/uv/kernel/machvec.c b/arch/ia64/uv/kernel/machvec.c new file mode 100644 index 0000000..50737a9 --- /dev/null +++ b/arch/ia64/uv/kernel/machvec.c @@ -0,0 +1,11 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (c) 2008 Silicon Graphics, Inc. All Rights Reserved. + */ + +#define MACHVEC_PLATFORM_NAME uv +#define MACHVEC_PLATFORM_HEADER +#include diff --git a/arch/ia64/uv/kernel/setup.c b/arch/ia64/uv/kernel/setup.c new file mode 100644 index 0000000..9aa7432 --- /dev/null +++ b/arch/ia64/uv/kernel/setup.c @@ -0,0 +1,98 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * SGI UV Core Functions + * + * Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved. + */ + +#include +#include +#include +#include +#include + +DEFINE_PER_CPU(struct uv_hub_info_s, __uv_hub_info); +EXPORT_PER_CPU_SYMBOL_GPL(__uv_hub_info); + + +struct redir_addr { + unsigned long redirect; + unsigned long alias; +}; + +#define DEST_SHIFT UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR_DEST_BASE_SHFT + +static __initdata struct redir_addr redir_addrs[] = { + {UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_0_MMR, UVH_SI_ALIAS0_OVERLAY_CONFIG}, + {UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_1_MMR, UVH_SI_ALIAS1_OVERLAY_CONFIG}, + {UVH_RH_GAM_ALIAS210_REDIRECT_CONFIG_2_MMR, UVH_SI_ALIAS2_OVERLAY_CONFIG}, +}; + +static __init void get_lowmem_redirect(unsigned long *base, unsigned long *size) +{ + union uvh_si_alias0_overlay_config_u alias; + union uvh_rh_gam_alias210_redirect_config_2_mmr_u redirect; + int i; + + for (i = 0; i < ARRAY_SIZE(redir_addrs); i++) { + alias.v = uv_read_local_mmr(redir_addrs[i].alias); + if (alias.s.base == 0) { + *size = (1UL << alias.s.m_alias); + redirect.v = uv_read_local_mmr(redir_addrs[i].redirect); + *base = (unsigned long)redirect.s.dest_base << DEST_SHIFT; + return; + } + } + BUG(); +} + +void __init uv_setup(char **cmdline_p) +{ + union uvh_si_addr_map_config_u m_n_config; + union uvh_node_id_u node_id; + unsigned long gnode_upper; + int nid, cpu, m_val, n_val; + unsigned long mmr_base, lowmem_redir_base, lowmem_redir_size; + + if (IS_MEDUSA()) { + lowmem_redir_base = 0; + lowmem_redir_size = 0; + node_id.v = 0; + m_n_config.s.m_skt = 37; + m_n_config.s.n_skt = 0; + mmr_base = 0; + } else { + get_lowmem_redirect(&lowmem_redir_base, &lowmem_redir_size); + node_id.v = uv_read_local_mmr(UVH_NODE_ID); + m_n_config.v = uv_read_local_mmr(UVH_SI_ADDR_MAP_CONFIG); + mmr_base = + uv_read_local_mmr(UVH_RH_GAM_MMR_OVERLAY_CONFIG_MMR) & + ~UV_MMR_ENABLE; + } + + m_val = m_n_config.s.m_skt; + n_val = m_n_config.s.n_skt; + printk(KERN_DEBUG "UV: global MMR base 0x%lx\n", mmr_base); + + gnode_upper = (((unsigned long)node_id.s.node_id) & + ~((1 << n_val) - 1)) << m_val; + + for_each_present_cpu(cpu) { + nid = cpu_to_node(cpu); + uv_cpu_hub_info(cpu)->lowmem_remap_base = lowmem_redir_base; + uv_cpu_hub_info(cpu)->lowmem_remap_top = + lowmem_redir_base + lowmem_redir_size; + uv_cpu_hub_info(cpu)->m_val = m_val; + uv_cpu_hub_info(cpu)->n_val = m_val; + uv_cpu_hub_info(cpu)->pnode_mask = (1 << n_val) -1; + uv_cpu_hub_info(cpu)->gpa_mask = (1 << (m_val + n_val)) - 1; + uv_cpu_hub_info(cpu)->gnode_upper = gnode_upper; + uv_cpu_hub_info(cpu)->global_mmr_base = mmr_base; + uv_cpu_hub_info(cpu)->coherency_domain_number = 0;/* ZZZ */ + printk(KERN_DEBUG "UV cpu %d, nid %d\n", cpu, nid); + } +} + diff --git a/include/asm-ia64/machvec.h b/include/asm-ia64/machvec.h index 9f020eb..0721a5e 100644 --- a/include/asm-ia64/machvec.h +++ b/include/asm-ia64/machvec.h @@ -126,6 +126,8 @@ extern void machvec_tlb_migrate_finish (struct mm_struct *); # include # elif defined (CONFIG_IA64_SGI_SN2) # include +# elif defined (CONFIG_IA64_SGI_UV) +# include # elif defined (CONFIG_IA64_GENERIC) # ifdef MACHVEC_PLATFORM_HEADER diff --git a/include/asm-ia64/machvec_uv.h b/include/asm-ia64/machvec_uv.h new file mode 100644 index 0000000..2931447 --- /dev/null +++ b/include/asm-ia64/machvec_uv.h @@ -0,0 +1,26 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * SGI UV Core Functions + * + * Copyright (C) 2008 Silicon Graphics, Inc. All rights reserved. + */ + +#ifndef _ASM_IA64_MACHVEC_UV_H +#define _ASM_IA64_MACHVEC_UV_H + +extern ia64_mv_setup_t uv_setup; + +/* + * This stuff has dual use! + * + * For a generic kernel, the macros are used to initialize the + * platform's machvec structure. When compiling a non-generic kernel, + * the macros are used directly. + */ +#define platform_name "uv" +#define platform_setup uv_setup + +#endif /* _ASM_IA64_MACHVEC_UV_H */ -- cgit v1.1 From 8a3360f06cd4d3b1d57f73e029f2f8b6057fdcba Mon Sep 17 00:00:00 2001 From: Bernhard Walle Date: Wed, 14 May 2008 15:40:40 -0700 Subject: [IA64] Don't reserve crashkernel memory > 4 GB Some IA64 machines map all cell-local memory above 4 GB (32 bit limit). However, in most cases, the kernel needs some memory below that limit that is DMA-capable. So in this machine configuration, the crashkernel will be reserved above 4 GB. For machines that use SWIOTLB implementation because they lack an I/O MMU the low memory is required by the SWIOTLB implementation. In that case, it doesn't make sense to reserve the crashkernel at all because it's unusable for kdump. A special case is the "hpzx1" machine vector. In theory, it has a I/O MMU, so it can be booted above 4 GB. However, in the kdump case that is not possible because of changeset 51b58e3e26ebfb8cd56825c4b396ed251f51dec9: On HP zx1 machines, the 'machvec=dig' parameter is needed for the kdump kernel to avoid problems with the HP sba iommu. The problem is that during the boot of the kdump kernel, the iommu is re-initialized, so in-flight DMA from improperly shutdown drivers causes an IOTLB miss which leads to an MCA. With kdump, the idea is to get into the kdump kernel with as little code as we can, so shutting down drivers properly is not an option. The workaround is to add 'machvec=dig' to the kdump kernel boot parameters. This makes the kdump kernel avoid using the sba iommu altogether, leaving the IOTLB intact. Any ongoing DMA falls harmlessly outside the kdump kernel. After the kdump kernel reboots, all devices will have been shutdown properly and DMA stopped. This patch pushes that functionality into the sba iommu initialization code, so that users won't have to find the obscure documentation telling them about 'machvec=dig'. This means that also for hpzx1 it's not possible to boot when all memory is above the 4 GB limit. So the only machine vectors that can handle this case are "sn2" and "uv". Signed-off-by: Bernhard Walle Signed-off-by: Tony Luck --- arch/ia64/kernel/setup.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 5015ca1..e9596cd 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -239,6 +239,25 @@ __initcall(register_memory); #ifdef CONFIG_KEXEC + +/* + * This function checks if the reserved crashkernel is allowed on the specific + * IA64 machine flavour. Machines without an IO TLB use swiotlb and require + * some memory below 4 GB (i.e. in 32 bit area), see the implementation of + * lib/swiotlb.c. The hpzx1 architecture has an IO TLB but cannot use that + * in kdump case. See the comment in sba_init() in sba_iommu.c. + * + * So, the only machvec that really supports loading the kdump kernel + * over 4 GB is "sn2". + */ +static int __init check_crashkernel_memory(unsigned long pbase, size_t size) +{ + if (ia64_platform_is("sn2") || ia64_platform_is("uv")) + return 1; + else + return pbase < (1UL << 32); +} + static void __init setup_crashkernel(unsigned long total, int *n) { unsigned long long base = 0, size = 0; @@ -252,6 +271,16 @@ static void __init setup_crashkernel(unsigned long total, int *n) base = kdump_find_rsvd_region(size, rsvd_region, *n); } + + if (!check_crashkernel_memory(base, size)) { + pr_warning("crashkernel: There would be kdump memory " + "at %ld GB but this is unusable because it " + "must\nbe below 4 GB. Change the memory " + "configuration of the machine.\n", + (unsigned long)(base >> 30)); + return; + } + if (base != ~0UL) { printk(KERN_INFO "Reserving %ldMB of memory at %ldMB " "for crashkernel (System RAM: %ldMB)\n", -- cgit v1.1 From f13ae30e1397e3bfb38feb3b6e889af5d021f13d Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Thu, 8 May 2008 14:03:23 -0600 Subject: [IA64] allow user to force_pal_cache_flush The sequence executed in check_sal_cache_flush: - pend a timer interrupt - call SAL_CACHE_FLUSH - see if interrupt is still pending can hang HP machines with buggy SAL_CACHE_FLUSH implementations. Provide a kernel command-line argument to allow users skip this check if desired. Using this parameter will force ia64_sal_cache_flush to call ia64_pal_cache_flush() instead of SAL_CACHE_FLUSH. Signed-off-by: Alex Chiang Signed-off-by: Tony Luck --- Documentation/kernel-parameters.txt | 6 ++++++ arch/ia64/kernel/sal.c | 11 +++++++++++ 2 files changed, 17 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index cdd5b93..654d630 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -689,6 +689,12 @@ and is between 256 and 4096 characters. It is defined in the file floppy= [HW] See Documentation/floppy.txt. + force_pal_cache_flush + [IA-64] Avoid check_sal_cache_flush which may hang on + buggy SAL_CACHE_FLUSH implementations. Using this + parameter will force ia64_sal_cache_flush to call + ia64_pal_cache_flush instead of SAL_CACHE_FLUSH. + gamecon.map[2|3]= [HW,JOY] Multisystem joystick and NES/SNES/PSX pad support via parallel port (up to 5 devices per port) diff --git a/arch/ia64/kernel/sal.c b/arch/ia64/kernel/sal.c index a3022dc..7e02597 100644 --- a/arch/ia64/kernel/sal.c +++ b/arch/ia64/kernel/sal.c @@ -229,6 +229,14 @@ static void __init sal_desc_ap_wakeup(void *p) { } */ static int sal_cache_flush_drops_interrupts; +static int __init +force_pal_cache_flush(char *str) +{ + sal_cache_flush_drops_interrupts = 1; + return 0; +} +early_param("force_pal_cache_flush", force_pal_cache_flush); + void __init check_sal_cache_flush (void) { @@ -237,6 +245,9 @@ check_sal_cache_flush (void) u64 vector, cache_type = 3; struct ia64_sal_retval isrv; + if (sal_cache_flush_drops_interrupts) + return; + cpu = get_cpu(); local_irq_save(flags); -- cgit v1.1 From 3633c7308005e8c1dab594f69ef904424f8b639a Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Fri, 9 May 2008 15:26:35 +0900 Subject: [IA64] fix interrupt masking for pending works on kernel leave [Bug-fix for "[BUG?][2.6.25-mm1] sleeping during IRQ disabled"] This patch does: - enable interrupts before calling schedule() as same as others, ex. x86 - enable interrupts during ia64_do_signal() and ia64_sync_krbs() - do_notify_resume_user() is still called with interrupts disabled, since we can take short path of fsys_mode if-statement quickly. - pfm_handle_work() is also called with interrupts disabled, since it can deal interrupt mask within itself. - fix/add some comments/notes Reported-by: KOSAKI Motohiro Signed-off-by: Hidetoshi Seto Signed-off-by: Tony Luck --- arch/ia64/kernel/entry.S | 14 ++++++++++---- arch/ia64/kernel/process.c | 25 +++++++++++++++++++++---- 2 files changed, 31 insertions(+), 8 deletions(-) diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index e49ad8c..ef6b031 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1156,6 +1156,9 @@ skip_rbs_switch: * r31 = current->thread_info->flags * On exit: * p6 = TRUE if work-pending-check needs to be redone + * + * Interrupts are disabled on entry, reenabled depend on work, and + * disabled on exit. */ .work_pending_syscall: add r2=-8,r2 @@ -1170,8 +1173,8 @@ skip_rbs_switch: (pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1 ;; (pKStk) st4 [r20]=r21 - ssm psr.i // enable interrupts #endif + ssm psr.i // enable interrupts br.call.spnt.many rp=schedule .ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1 rsm psr.i // disable interrupts @@ -1234,9 +1237,12 @@ GLOBAL_ENTRY(ia64_invoke_schedule_tail) END(ia64_invoke_schedule_tail) /* - * Setup stack and call do_notify_resume_user(). Note that pSys and pNonSys need to - * be set up by the caller. We declare 8 input registers so the system call - * args get preserved, in case we need to restart a system call. + * Setup stack and call do_notify_resume_user(), keeping interrupts + * disabled. + * + * Note that pSys and pNonSys need to be set up by the caller. + * We declare 8 input registers so the system call args get preserved, + * in case we need to restart a system call. */ ENTRY(notify_resume_user) .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c index 58dcfac..a3a34b4 100644 --- a/arch/ia64/kernel/process.c +++ b/arch/ia64/kernel/process.c @@ -167,11 +167,18 @@ void tsk_clear_notify_resume(struct task_struct *tsk) clear_ti_thread_flag(task_thread_info(tsk), TIF_NOTIFY_RESUME); } +/* + * do_notify_resume_user(): + * Called from notify_resume_user at entry.S, with interrupts disabled. + */ void -do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall) +do_notify_resume_user(sigset_t *unused, struct sigscratch *scr, long in_syscall) { if (fsys_mode(current, &scr->pt)) { - /* defer signal-handling etc. until we return to privilege-level 0. */ + /* + * defer signal-handling etc. until we return to + * privilege-level 0. + */ if (!ia64_psr(&scr->pt)->lp) ia64_psr(&scr->pt)->lp = 1; return; @@ -179,16 +186,26 @@ do_notify_resume_user (sigset_t *unused, struct sigscratch *scr, long in_syscall #ifdef CONFIG_PERFMON if (current->thread.pfm_needs_checking) + /* + * Note: pfm_handle_work() allow us to call it with interrupts + * disabled, and may enable interrupts within the function. + */ pfm_handle_work(); #endif /* deal with pending signal delivery */ - if (test_thread_flag(TIF_SIGPENDING)) + if (test_thread_flag(TIF_SIGPENDING)) { + local_irq_enable(); /* force interrupt enable */ ia64_do_signal(scr, in_syscall); + } /* copy user rbs to kernel rbs */ - if (unlikely(test_thread_flag(TIF_RESTORE_RSE))) + if (unlikely(test_thread_flag(TIF_RESTORE_RSE))) { + local_irq_enable(); /* force interrupt enable */ ia64_sync_krbs(); + } + + local_irq_disable(); /* force interrupt disable */ } static int pal_halt = 1; -- cgit v1.1 From 2e513fe4903c62450a9f8c3759f75bc4cd7e4dfd Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Fri, 9 May 2008 15:26:51 +0900 Subject: [IA64] trivial cleanup for entry.S This patch does: - make comment at next to resched check more robust - move "re-check" comments to next to where change predicate regs Signed-off-by: Hidetoshi Seto Signed-off-by: Tony Luck --- arch/ia64/kernel/entry.S | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/ia64/kernel/entry.S b/arch/ia64/kernel/entry.S index ef6b031..ca2bb95 100644 --- a/arch/ia64/kernel/entry.S +++ b/arch/ia64/kernel/entry.S @@ -1167,7 +1167,7 @@ skip_rbs_switch: st8 [r2]=r8 st8 [r3]=r10 .work_pending: - tbit.z p6,p0=r31,TIF_NEED_RESCHED // current_thread_info()->need_resched==0? + tbit.z p6,p0=r31,TIF_NEED_RESCHED // is resched not needed? (p6) br.cond.sptk.few .notify #ifdef CONFIG_PREEMPT (pKStk) dep r21=-1,r0,PREEMPT_ACTIVE_BIT,1 @@ -1176,7 +1176,7 @@ skip_rbs_switch: #endif ssm psr.i // enable interrupts br.call.spnt.many rp=schedule -.ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1 +.ret9: cmp.eq p6,p0=r0,r0 // p6 <- 1 (re-check) rsm psr.i // disable interrupts ;; #ifdef CONFIG_PREEMPT @@ -1185,13 +1185,13 @@ skip_rbs_switch: (pKStk) st4 [r20]=r0 // preempt_count() <- 0 #endif (pLvSys)br.cond.sptk.few .work_pending_syscall_end - br.cond.sptk.many .work_processed_kernel // re-check + br.cond.sptk.many .work_processed_kernel .notify: (pUStk) br.call.spnt.many rp=notify_resume_user -.ret10: cmp.ne p6,p0=r0,r0 // p6 <- 0 +.ret10: cmp.ne p6,p0=r0,r0 // p6 <- 0 (don't re-check) (pLvSys)br.cond.sptk.few .work_pending_syscall_end - br.cond.sptk.many .work_processed_kernel // don't re-check + br.cond.sptk.many .work_processed_kernel .work_pending_syscall_end: adds r2=PT(R8)+16,r12 @@ -1199,7 +1199,7 @@ skip_rbs_switch: ;; ld8 r8=[r2] ld8 r10=[r3] - br.cond.sptk.many .work_processed_syscall // re-check + br.cond.sptk.many .work_processed_syscall END(ia64_leave_kernel) -- cgit v1.1 From 0fb232fdb2a2674003ef4b874034e872b7256aa9 Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Fri, 9 May 2008 15:27:09 +0900 Subject: [IA64] trivial cleanup for perfmon.c Fix a typo, and coding style cleanups for pfm_handle_work(). Signed-off-by: Hidetoshi Seto Signed-off-by: Tony Luck --- arch/ia64/kernel/perfmon.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index c1ad27d..71d0513 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -5013,12 +5013,13 @@ pfm_context_force_terminate(pfm_context_t *ctx, struct pt_regs *regs) } static int pfm_ovfl_notify_user(pfm_context_t *ctx, unsigned long ovfl_pmds); + /* * pfm_handle_work() can be called with interrupts enabled * (TIF_NEED_RESCHED) or disabled. The down_interruptible * call may sleep, therefore we must re-enable interrupts * to avoid deadlocks. It is safe to do so because this function - * is called ONLY when returning to user level (PUStk=1), in which case + * is called ONLY when returning to user level (pUStk=1), in which case * there is no risk of kernel stack overflow due to deep * interrupt nesting. */ @@ -5034,7 +5035,8 @@ pfm_handle_work(void) ctx = PFM_GET_CTX(current); if (ctx == NULL) { - printk(KERN_ERR "perfmon: [%d] has no PFM context\n", task_pid_nr(current)); + printk(KERN_ERR "perfmon: [%d] has no PFM context\n", + task_pid_nr(current)); return; } @@ -5058,11 +5060,12 @@ pfm_handle_work(void) /* * must be done before we check for simple-reset mode */ - if (ctx->ctx_fl_going_zombie || ctx->ctx_state == PFM_CTX_ZOMBIE) goto do_zombie; - + if (ctx->ctx_fl_going_zombie || ctx->ctx_state == PFM_CTX_ZOMBIE) + goto do_zombie; //if (CTX_OVFL_NOBLOCK(ctx)) goto skip_blocking; - if (reason == PFM_TRAP_REASON_RESET) goto skip_blocking; + if (reason == PFM_TRAP_REASON_RESET) + goto skip_blocking; /* * restore interrupt mask to what it was on entry. @@ -5110,7 +5113,8 @@ do_zombie: /* * in case of interruption of down() we don't restart anything */ - if (ret < 0) goto nothing_to_do; + if (ret < 0) + goto nothing_to_do; skip_blocking: pfm_resume_after_ovfl(ctx, ovfl_regs, regs); -- cgit v1.1 From 7af1d7532b6cf905230c72c67ad85a480b122374 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Holm=20Th=C3=B8gersen?= Date: Mon, 12 May 2008 17:40:50 +0200 Subject: [IA64] Remove NULL pointer check for argument never passed as NULL. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is only palinfo_handle_smp as (indirect) user of palinfo_smp_call (by way of smp_call_function_single) and surely palinfo_handle_smp never pass NULL as parameter for info. Signed-off-by: Simon Holm Thøgersen Signed-off-by: Tony Luck --- arch/ia64/kernel/palinfo.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c index 4547a20..9dc00f7 100644 --- a/arch/ia64/kernel/palinfo.c +++ b/arch/ia64/kernel/palinfo.c @@ -900,12 +900,6 @@ static void palinfo_smp_call(void *info) { palinfo_smp_data_t *data = (palinfo_smp_data_t *)info; - if (data == NULL) { - printk(KERN_ERR "palinfo: data pointer is NULL\n"); - data->ret = 0; /* no output */ - return; - } - /* does this actual call */ data->ret = (*data->func)(data->page); } -- cgit v1.1 From 3fb2c74ee20b77affd494c6b8ce7928d0ebbb62e Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Wed, 14 May 2008 12:00:24 -0400 Subject: [IA64] Properly unregister legacy interrupts acpi_unregister_gsi() should "undo" what acpi_register_gsi() does. On systems that have legacy interrupts, acpi_unregister_gsi erroneously calls iosapci_unregister_intr() which is wrong to do and causes a loud warning. acpi_unregister_gsi() should just return in these cases. Signed-off-by: Prarit Bhargava Signed-off-by: Tony Luck --- arch/ia64/kernel/acpi.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/ia64/kernel/acpi.c b/arch/ia64/kernel/acpi.c index 6ff6815..853d1f1 100644 --- a/arch/ia64/kernel/acpi.c +++ b/arch/ia64/kernel/acpi.c @@ -627,6 +627,9 @@ void acpi_unregister_gsi(u32 gsi) if (acpi_irq_model == ACPI_IRQ_MODEL_PLATFORM) return; + if (has_8259 && gsi < 16) + return; + iosapic_unregister_intr(gsi); } -- cgit v1.1 From b32a09db4fb9a87246ba4e7726a979ac4709ad97 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Tue, 26 Feb 2008 09:57:11 -0600 Subject: add match_strlcpy() us it to make v9fs make uname and remotename parsing more robust match_strcpy() is a somewhat creepy function: the caller needs to make sure that the destination buffer is big enough, and when he screws up or forgets, match_strcpy() happily overruns the buffer. There's exactly one customer: v9fs_parse_options(). I believe it currently can't overflow its buffer, but that's not exactly obvious. The source string is a substing of the mount options. The kernel silently truncates those to PAGE_SIZE bytes, including the terminating zero. See compat_sys_mount() and do_mount(). The destination buffer is obtained from __getname(), which allocates from name_cachep, which is initialized by vfs_caches_init() for size PATH_MAX. We're safe as long as PATH_MAX <= PAGE_SIZE. PATH_MAX is 4096. As far as I know, the smallest PAGE_SIZE is also 4096. Here's a patch that makes the code a bit more obviously correct. It doesn't depend on PATH_MAX <= PAGE_SIZE. Signed-off-by: Markus Armbruster Cc: Latchesar Ionkov Cc: Jim Meyering Cc: "Randy.Dunlap" Signed-off-by: Andrew Morton Signed-off-by: Eric Van Hensbergen --- fs/9p/v9fs.c | 4 ++-- include/linux/parser.h | 2 +- lib/parser.c | 32 ++++++++++++++++++++------------ 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 9b0f022..e307fbd 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -125,10 +125,10 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses) v9ses->afid = option; break; case Opt_uname: - match_strcpy(v9ses->uname, &args[0]); + match_strlcpy(v9ses->uname, &args[0], PATH_MAX); break; case Opt_remotename: - match_strcpy(v9ses->aname, &args[0]); + match_strlcpy(v9ses->aname, &args[0], PATH_MAX); break; case Opt_nodevmap: v9ses->nodev = 1; diff --git a/include/linux/parser.h b/include/linux/parser.h index 26b2bdf..7dcd050 100644 --- a/include/linux/parser.h +++ b/include/linux/parser.h @@ -29,5 +29,5 @@ int match_token(char *, match_table_t table, substring_t args[]); int match_int(substring_t *, int *result); int match_octal(substring_t *, int *result); int match_hex(substring_t *, int *result); -void match_strcpy(char *, const substring_t *); +size_t match_strlcpy(char *, const substring_t *, size_t); char *match_strdup(const substring_t *); diff --git a/lib/parser.c b/lib/parser.c index 703c8c1..4f0cbc0 100644 --- a/lib/parser.c +++ b/lib/parser.c @@ -182,18 +182,25 @@ int match_hex(substring_t *s, int *result) } /** - * match_strcpy: - copies the characters from a substring_t to a string - * @to: string to copy characters to. - * @s: &substring_t to copy + * match_strlcpy: - Copy the characters from a substring_t to a sized buffer + * @dest: where to copy to + * @src: &substring_t to copy + * @size: size of destination buffer * - * Description: Copies the set of characters represented by the given - * &substring_t @s to the c-style string @to. Caller guarantees that @to is - * large enough to hold the characters of @s. + * Description: Copy the characters in &substring_t @src to the + * c-style string @dest. Copy no more than @size - 1 characters, plus + * the terminating NUL. Return length of @src. */ -void match_strcpy(char *to, const substring_t *s) +size_t match_strlcpy(char *dest, const substring_t *src, size_t size) { - memcpy(to, s->from, s->to - s->from); - to[s->to - s->from] = '\0'; + size_t ret = src->to - src->from; + + if (size) { + size_t len = ret >= size ? size - 1 : ret; + memcpy(dest, src->from, len); + dest[len] = '\0'; + } + return ret; } /** @@ -206,9 +213,10 @@ void match_strcpy(char *to, const substring_t *s) */ char *match_strdup(const substring_t *s) { - char *p = kmalloc(s->to - s->from + 1, GFP_KERNEL); + size_t sz = s->to - s->from + 1; + char *p = kmalloc(sz, GFP_KERNEL); if (p) - match_strcpy(p, s); + match_strlcpy(p, s, sz); return p; } @@ -216,5 +224,5 @@ EXPORT_SYMBOL(match_token); EXPORT_SYMBOL(match_int); EXPORT_SYMBOL(match_octal); EXPORT_SYMBOL(match_hex); -EXPORT_SYMBOL(match_strcpy); +EXPORT_SYMBOL(match_strlcpy); EXPORT_SYMBOL(match_strdup); -- cgit v1.1 From ee443996a35c1e04f210cafd43d5a98d41e46085 Mon Sep 17 00:00:00 2001 From: Eric Van Hensbergen Date: Wed, 5 Mar 2008 07:08:09 -0600 Subject: 9p: Documentation updates The kernel-doc comments of much of the 9p system have been in disarray since reorganization. This patch fixes those problems, adds additional documentation and a template book which collects the 9p information. Signed-off-by: Eric Van Hensbergen --- fs/9p/fid.h | 15 +++ fs/9p/v9fs.c | 8 +- fs/9p/v9fs.h | 85 +++++++++++----- fs/9p/vfs_addr.c | 2 +- fs/9p/vfs_dir.c | 2 +- fs/9p/vfs_file.c | 11 ++- fs/9p/vfs_inode.c | 50 +++++++--- fs/9p/vfs_super.c | 1 + include/net/9p/9p.h | 239 +++++++++++++++++++++++++++++++++++++++------ include/net/9p/client.h | 35 +++++++ include/net/9p/transport.h | 43 ++++++++ net/9p/conv.c | 128 +++++++++++++++++++++++- net/9p/error.c | 11 ++- net/9p/fcprint.c | 8 ++ net/9p/mod.c | 7 +- net/9p/trans_fd.c | 146 ++++++++++++++++++++++----- net/9p/trans_virtio.c | 155 +++++++++++++++++++++++++++-- net/9p/util.c | 32 ++++-- 18 files changed, 854 insertions(+), 124 deletions(-) diff --git a/fs/9p/fid.h b/fs/9p/fid.h index 26e07df..c3bbd6a 100644 --- a/fs/9p/fid.h +++ b/fs/9p/fid.h @@ -22,6 +22,21 @@ #include +/** + * struct v9fs_dentry - 9p private data stored in dentry d_fsdata + * @lock: protects the fidlist + * @fidlist: list of FIDs currently associated with this dentry + * + * This structure defines the 9p private data associated with + * a particular dentry. In particular, this private data is used + * to lookup which 9P FID handle should be used for a particular VFS + * operation. FID handles are associated with dentries instead of + * inodes in order to more closely map functionality to the Plan 9 + * expected behavior for FID reclaimation and tracking. + * + * See Also: Mapping FIDs to Linux VFS model in + * Design and Implementation of the Linux 9P File System documentation + */ struct v9fs_dentry { spinlock_t lock; /* protect fidlist */ struct list_head fidlist; diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index e307fbd..79d310c 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -71,7 +71,6 @@ static match_table_t tokens = { /** * v9fs_parse_options - parse mount options into session structure - * @options: options string passed from mount * @v9ses: existing v9fs session information * */ @@ -256,9 +255,12 @@ void v9fs_session_close(struct v9fs_session_info *v9ses) } /** - * v9fs_session_cancel - mark transport as disconnected - * and cancel all pending requests. + * v9fs_session_cancel - terminate a session + * @v9ses: session to terminate + * + * mark transport as disconnected and cancel all pending requests. */ + void v9fs_session_cancel(struct v9fs_session_info *v9ses) { P9_DPRINTK(P9_DEBUG_ERROR, "cancel session %p\n", v9ses); p9_client_disconnect(v9ses->clnt); diff --git a/fs/9p/v9fs.h b/fs/9p/v9fs.h index 7d3a101..a7d5671 100644 --- a/fs/9p/v9fs.h +++ b/fs/9p/v9fs.h @@ -21,18 +21,69 @@ * */ -/* - * Session structure provides information for an opened session - * - */ +/** + * enum p9_session_flags - option flags for each 9P session + * @V9FS_EXTENDED: whether or not to use 9P2000.u extensions + * @V9FS_ACCESS_SINGLE: only the mounting user can access the hierarchy + * @V9FS_ACCESS_USER: a new attach will be issued for every user (default) + * @V9FS_ACCESS_ANY: use a single attach for all users + * @V9FS_ACCESS_MASK: bit mask of different ACCESS options + * + * Session flags reflect options selected by users at mount time + */ +enum p9_session_flags { + V9FS_EXTENDED = 0x01, + V9FS_ACCESS_SINGLE = 0x02, + V9FS_ACCESS_USER = 0x04, + V9FS_ACCESS_ANY = 0x06, + V9FS_ACCESS_MASK = 0x06, +}; + +/* possible values of ->cache */ +/** + * enum p9_cache_modes - user specified cache preferences + * @CACHE_NONE: do not cache data, dentries, or directory contents (default) + * @CACHE_LOOSE: cache data, dentries, and directory contents w/no consistency + * + * eventually support loose, tight, time, session, default always none + */ + +enum p9_cache_modes { + CACHE_NONE, + CACHE_LOOSE, +}; + +/** + * struct v9fs_session_info - per-instance session information + * @flags: session options of type &p9_session_flags + * @nodev: set to 1 to disable device mapping + * @debug: debug level + * @afid: authentication handle + * @cache: cache mode of type &p9_cache_modes + * @options: copy of options string given by user + * @uname: string user name to mount hierarchy as + * @aname: mount specifier for remote hierarchy + * @maxdata: maximum data to be sent/recvd per protocol message + * @dfltuid: default numeric userid to mount hierarchy as + * @dfltgid: default numeric groupid to mount hierarchy as + * @uid: if %V9FS_ACCESS_SINGLE, the numeric uid which mounted the hierarchy + * @clnt: reference to 9P network client instantiated for this session + * @debugfs_dir: reference to debugfs_dir which can be used for add'l debug + * + * This structure holds state for each session instance established during + * a sys_mount() . + * + * Bugs: there seems to be a lot of state which could be condensed and/or + * removed. + */ struct v9fs_session_info { /* options */ - unsigned char flags; /* session flags */ - unsigned char nodev; /* set to 1 if no disable device mapping */ - unsigned short debug; /* debug level */ - unsigned int afid; /* authentication fid */ - unsigned int cache; /* cache mode */ + unsigned char flags; + unsigned char nodev; + unsigned short debug; + unsigned int afid; + unsigned int cache; char *options; /* copy of mount options */ char *uname; /* user name to mount as */ @@ -45,22 +96,6 @@ struct v9fs_session_info { struct dentry *debugfs_dir; }; -/* session flags */ -enum { - V9FS_EXTENDED = 0x01, /* 9P2000.u */ - V9FS_ACCESS_MASK = 0x06, /* access mask */ - V9FS_ACCESS_SINGLE = 0x02, /* only one user can access the files */ - V9FS_ACCESS_USER = 0x04, /* attache per user */ - V9FS_ACCESS_ANY = 0x06, /* use the same attach for all users */ -}; - -/* possible values of ->cache */ -/* eventually support loose, tight, time, session, default always none */ -enum { - CACHE_NONE, /* default */ - CACHE_LOOSE, /* no consistency */ -}; - extern struct dentry *v9fs_debugfs_root; struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *, diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c index 6248f0e..97d3aed 100644 --- a/fs/9p/vfs_addr.c +++ b/fs/9p/vfs_addr.c @@ -43,7 +43,7 @@ /** * v9fs_vfs_readpage - read an entire page in from 9P * - * @file: file being read + * @filp: file being read * @page: structure to page * */ diff --git a/fs/9p/vfs_dir.c b/fs/9p/vfs_dir.c index 0924d44..88e3787 100644 --- a/fs/9p/vfs_dir.c +++ b/fs/9p/vfs_dir.c @@ -60,7 +60,7 @@ static inline int dt_type(struct p9_stat *mistat) /** * v9fs_dir_readdir - read a directory - * @filep: opened file structure + * @filp: opened file structure * @dirent: directory structure ??? * @filldir: function to populate directory structure ??? * diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index a616fff..0d55aff 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -90,10 +90,11 @@ int v9fs_file_open(struct inode *inode, struct file *file) /** * v9fs_file_lock - lock a file (or directory) - * @inode: inode to be opened - * @file: file being opened + * @filp: file to be locked + * @cmd: lock command + * @fl: file lock structure * - * XXX - this looks like a local only lock, we should extend into 9P + * Bugs: this looks like a local only lock, we should extend into 9P * by using open exclusive */ @@ -118,7 +119,7 @@ static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) /** * v9fs_file_read - read from a file - * @filep: file pointer to read + * @filp: file pointer to read * @data: data buffer to read data into * @count: size of buffer * @offset: offset at which to read data @@ -142,7 +143,7 @@ v9fs_file_read(struct file *filp, char __user * data, size_t count, /** * v9fs_file_write - write to a file - * @filep: file pointer to write + * @filp: file pointer to write * @data: data buffer to write data from * @count: size of buffer * @offset: offset at which to write data diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c index 6a28842..40fa807 100644 --- a/fs/9p/vfs_inode.c +++ b/fs/9p/vfs_inode.c @@ -129,6 +129,12 @@ static int p9mode2unixmode(struct v9fs_session_info *v9ses, int mode) return res; } +/** + * v9fs_uflags2omode- convert posix open flags to plan 9 mode bits + * @uflags: flags to convert + * + */ + int v9fs_uflags2omode(int uflags) { int ret; @@ -312,6 +318,14 @@ error: } */ +/** + * v9fs_inode_from_fid - populate an inode by issuing a attribute request + * @v9ses: session information + * @fid: fid to issue attribute request for + * @sb: superblock on which to create inode + * + */ + static struct inode * v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, struct super_block *sb) @@ -384,9 +398,12 @@ v9fs_open_created(struct inode *inode, struct file *file) /** * v9fs_create - Create a file + * @v9ses: session information + * @dir: directory that dentry is being created in * @dentry: dentry that is being created * @perm: create permissions * @mode: open mode + * @extension: 9p2000.u extension string to support devices, etc. * */ static struct p9_fid * @@ -461,7 +478,7 @@ error: /** * v9fs_vfs_create - VFS hook to create files - * @inode: directory inode that is being created + * @dir: directory inode that is being created * @dentry: dentry that is being deleted * @mode: create permissions * @nd: path information @@ -519,7 +536,7 @@ error: /** * v9fs_vfs_mkdir - VFS mkdir hook to create a directory - * @inode: inode that is being unlinked + * @dir: inode that is being unlinked * @dentry: dentry that is being unlinked * @mode: mode for new directory * @@ -703,9 +720,9 @@ done: /** * v9fs_vfs_getattr - retrieve file metadata - * @mnt - mount information - * @dentry - file to get attributes on - * @stat - metadata structure to populate + * @mnt: mount information + * @dentry: file to get attributes on + * @stat: metadata structure to populate * */ @@ -928,7 +945,7 @@ done: /** * v9fs_vfs_readlink - read a symlink's location * @dentry: dentry for symlink - * @buf: buffer to load symlink location into + * @buffer: buffer to load symlink location into * @buflen: length of buffer * */ @@ -996,10 +1013,12 @@ static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd) * v9fs_vfs_put_link - release a symlink path * @dentry: dentry for symlink * @nd: nameidata + * @p: unused * */ -static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) +static void +v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) { char *s = nd_get_link(nd); @@ -1008,6 +1027,15 @@ static void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void __putname(s); } +/** + * v9fs_vfs_mkspecial - create a special file + * @dir: inode to create special file in + * @dentry: dentry to create + * @mode: mode to create special file + * @extension: 9p2000.u format extension string representing special file + * + */ + static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, int mode, const char *extension) { @@ -1037,7 +1065,7 @@ static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, * @dentry: dentry for symlink * @symname: symlink data * - * See 9P2000.u RFC for more information + * See Also: 9P2000.u RFC for more information * */ @@ -1058,10 +1086,6 @@ v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) * */ -/* XXX - lots of code dup'd from symlink and creates, - * figure out a better reuse strategy - */ - static int v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) @@ -1098,7 +1122,7 @@ clunk_fid: * @dir: inode destination for new link * @dentry: dentry for file * @mode: mode for creation - * @dev_t: device associated with special file + * @rdev: device associated with special file * */ diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index a452ac6..ba10f17 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -75,6 +75,7 @@ static int v9fs_set_super(struct super_block *s, void *data) * v9fs_fill_super - populate superblock with info * @sb: superblock * @v9ses: session information + * @flags: flags propagated from v9fs_get_sb() * */ diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index 585eb44..7bfb2f2 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -29,14 +29,31 @@ #ifdef CONFIG_NET_9P_DEBUG -#define P9_DEBUG_ERROR (1<<0) -#define P9_DEBUG_9P (1<<2) -#define P9_DEBUG_VFS (1<<3) -#define P9_DEBUG_CONV (1<<4) -#define P9_DEBUG_MUX (1<<5) -#define P9_DEBUG_TRANS (1<<6) -#define P9_DEBUG_SLABS (1<<7) -#define P9_DEBUG_FCALL (1<<8) +/** + * enum p9_debug_flags - bits for mount time debug parameter + * @P9_DEBUG_ERROR: more verbose error messages including original error string + * @P9_DEBUG_9P: 9P protocol tracing + * @P9_DEBUG_VFS: VFS API tracing + * @P9_DEBUG_CONV: protocol conversion tracing + * @P9_DEBUG_MUX: trace management of concurrent transactions + * @P9_DEBUG_TRANS: transport tracing + * @P9_DEBUG_SLABS: memory management tracing + * @P9_DEBUG_FCALL: verbose dump of protocol messages + * + * These flags are passed at mount time to turn on various levels of + * verbosity and tracing which will be output to the system logs. + */ + +enum p9_debug_flags { + P9_DEBUG_ERROR = (1<<0), + P9_DEBUG_9P = (1<<2), + P9_DEBUG_VFS = (1<<3), + P9_DEBUG_CONV = (1<<4), + P9_DEBUG_MUX = (1<<5), + P9_DEBUG_TRANS = (1<<6), + P9_DEBUG_SLABS = (1<<7), + P9_DEBUG_FCALL = (1<<8), +}; extern unsigned int p9_debug_level; @@ -62,9 +79,47 @@ do { \ format , __FUNCTION__, task_pid_nr(current), ## arg); \ } while (0) +/** + * enum p9_msg_t - 9P message types + * @P9_TVERSION: version handshake request + * @P9_RVERSION: version handshake response + * @P9_TAUTH: request to establish authentication channel + * @P9_RAUTH: response with authentication information + * @P9_TATTACH: establish user access to file service + * @P9_RATTACH: response with top level handle to file hierarchy + * @P9_TERROR: not used + * @P9_RERROR: response for any failed request + * @P9_TFLUSH: request to abort a previous request + * @P9_RFLUSH: response when previous request has been cancelled + * @P9_TWALK: descend a directory hierarchy + * @P9_RWALK: response with new handle for position within hierarchy + * @P9_TOPEN: prepare a handle for I/O on an existing file + * @P9_ROPEN: response with file access information + * @P9_TCREATE: prepare a handle for I/O on a new file + * @P9_RCREATE: response with file access information + * @P9_TREAD: request to transfer data from a file or directory + * @P9_RREAD: response with data requested + * @P9_TWRITE: reuqest to transfer data to a file + * @P9_RWRITE: response with out much data was transfered to file + * @P9_TCLUNK: forget about a handle to an entity within the file system + * @P9_RCLUNK: response when server has forgotten about the handle + * @P9_TREMOVE: request to remove an entity from the hierarchy + * @P9_RREMOVE: response when server has removed the entity + * @P9_TSTAT: request file entity attributes + * @P9_RSTAT: response with file entity attributes + * @P9_TWSTAT: request to update file entity attributes + * @P9_RWSTAT: response when file entity attributes are updated + * + * There are 14 basic operations in 9P2000, paired as + * requests and responses. The one special case is ERROR + * as there is no @P9_TERROR request for clients to transmit to + * the server, but the server may respond to any other request + * with an @P9_RERROR. + * + * See Also: http://plan9.bell-labs.com/sys/man/5/INDEX.html + */ -/* Message Types */ -enum { +enum p9_msg_t { P9_TVERSION = 100, P9_RVERSION, P9_TAUTH = 102, @@ -95,30 +150,71 @@ enum { P9_RWSTAT, }; -/* open modes */ -enum { +/** + * enum p9_open_mode_t - 9P open modes + * @P9_OREAD: open file for reading only + * @P9_OWRITE: open file for writing only + * @P9_ORDWR: open file for reading or writing + * @P9_OEXEC: open file for execution + * @P9_OTRUNC: truncate file to zero-length before opening it + * @P9_OREXEC: close the file when an exec(2) system call is made + * @P9_ORCLOSE: remove the file when the file is closed + * @P9_OAPPEND: open the file and seek to the end + * @P9_OEXCL: only create a file, do not open it + * + * 9P open modes differ slightly from Posix standard modes. + * In particular, there are extra modes which specify different + * semantic behaviors than may be available on standard Posix + * systems. For example, @P9_OREXEC and @P9_ORCLOSE are modes that + * most likely will not be issued from the Linux VFS client, but may + * be supported by servers. + * + * See Also: http://plan9.bell-labs.com/magic/man2html/2/open + */ + +enum p9_open_mode_t { P9_OREAD = 0x00, P9_OWRITE = 0x01, P9_ORDWR = 0x02, P9_OEXEC = 0x03, - P9_OEXCL = 0x04, P9_OTRUNC = 0x10, P9_OREXEC = 0x20, P9_ORCLOSE = 0x40, P9_OAPPEND = 0x80, -}; - -/* permissions */ -enum { + P9_OEXCL = 0x1000, +}; + +/** + * enum p9_perm_t - 9P permissions + * @P9_DMDIR: mode bite for directories + * @P9_DMAPPEND: mode bit for is append-only + * @P9_DMEXCL: mode bit for excluse use (only one open handle allowed) + * @P9_DMMOUNT: mode bite for mount points + * @P9_DMAUTH: mode bit for authentication file + * @P9_DMTMP: mode bit for non-backed-up files + * @P9_DMSYMLINK: mode bit for symbolic links (9P2000.u) + * @P9_DMLINK: mode bit for hard-link (9P2000.u) + * @P9_DMDEVICE: mode bit for device files (9P2000.u) + * @P9_DMNAMEDPIPE: mode bit for named pipe (9P2000.u) + * @P9_DMSOCKET: mode bit for socket (9P2000.u) + * @P9_DMSETUID: mode bit for setuid (9P2000.u) + * @P9_DMSETGID: mode bit for setgid (9P2000.u) + * @P9_DMSETVTX: mode bit for sticky bit (9P2000.u) + * + * 9P permissions differ slightly from Posix standard modes. + * + * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat + */ +enum p9_perm_t { P9_DMDIR = 0x80000000, P9_DMAPPEND = 0x40000000, P9_DMEXCL = 0x20000000, P9_DMMOUNT = 0x10000000, P9_DMAUTH = 0x08000000, P9_DMTMP = 0x04000000, +/* 9P2000.u extensions */ P9_DMSYMLINK = 0x02000000, P9_DMLINK = 0x01000000, - /* 9P2000.u extensions */ P9_DMDEVICE = 0x00800000, P9_DMNAMEDPIPE = 0x00200000, P9_DMSOCKET = 0x00100000, @@ -127,8 +223,26 @@ enum { P9_DMSETVTX = 0x00010000, }; -/* qid.types */ -enum { +/** + * enum p9_qid_t - QID types + * @P9_QTDIR: directory + * @P9_QTAPPEND: append-only + * @P9_QTEXCL: excluse use (only one open handle allowed) + * @P9_QTMOUNT: mount points + * @P9_QTAUTH: authentication file + * @P9_QTTMP: non-backed-up files + * @P9_QTSYMLINK: symbolic links (9P2000.u) + * @P9_QTLINK: hard-link (9P2000.u) + * @P9_QTFILE: normal files + * + * QID types are a subset of permissions - they are primarily + * used to differentiate semantics for a file system entity via + * a jump-table. Their value is also the most signifigant 16 bits + * of the permission_t + * + * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat + */ +enum p9_qid_t { P9_QTDIR = 0x80, P9_QTAPPEND = 0x40, P9_QTEXCL = 0x20, @@ -140,6 +254,7 @@ enum { P9_QTFILE = 0x00, }; +/* 9P Magic Numbers */ #define P9_NOTAG (u16)(~0) #define P9_NOFID (u32)(~0) #define P9_MAXWELEM 16 @@ -147,19 +262,69 @@ enum { /* ample room for Twrite/Rread header */ #define P9_IOHDRSZ 24 +/** + * struct p9_str - length prefixed string type + * @len: length of the string + * @str: the string + * + * The protocol uses length prefixed strings for all + * string data, so we replicate that for our internal + * string members. + */ + struct p9_str { u16 len; char *str; }; -/* qids are the unique ID for a file (like an inode */ +/** + * struct p9_qid - file system entity information + * @type: 8-bit type &p9_qid_t + * @version: 16-bit monotonically incrementing version number + * @path: 64-bit per-server-unique ID for a file system element + * + * qids are identifiers used by 9P servers to track file system + * entities. The type is used to differentiate semantics for operations + * on the entity (ie. read means something different on a directory than + * on a file). The path provides a server unique index for an entity + * (roughly analogous to an inode number), while the version is updated + * every time a file is modified and can be used to maintain cache + * coherency between clients and serves. + * Servers will often differentiate purely synthetic entities by setting + * their version to 0, signaling that they should never be cached and + * should be accessed synchronously. + * + * See Also://plan9.bell-labs.com/magic/man2html/2/stat + */ + struct p9_qid { u8 type; u32 version; u64 path; }; -/* Plan 9 file metadata (stat) structure */ +/** + * struct p9_stat - file system metadata information + * @size: length prefix for this stat structure instance + * @type: the type of the server (equivilent to a major number) + * @dev: the sub-type of the server (equivilent to a minor number) + * @qid: unique id from the server of type &p9_qid + * @mode: Plan 9 format permissions of type &p9_perm_t + * @atime: Last access/read time + * @mtime: Last modify/write time + * @length: file length + * @name: last element of path (aka filename) in type &p9_str + * @uid: owner name in type &p9_str + * @gid: group owner in type &p9_str + * @muid: last modifier in type &p9_str + * @extension: area used to encode extended UNIX support in type &p9_str + * @n_uid: numeric user id of owner (part of 9p2000.u extension) + * @n_gid: numeric group id (part of 9p2000.u extension) + * @n_muid: numeric user id of laster modifier (part of 9p2000.u extension) + * + * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat + */ + struct p9_stat { u16 size; u16 type; @@ -179,10 +344,14 @@ struct p9_stat { u32 n_muid; /* 9p2000.u extensions */ }; -/* file metadata (stat) structure used to create Twstat message - The is similar to p9_stat, but the strings don't point to - the same memory block and should be freed separately -*/ +/* + * file metadata (stat) structure used to create Twstat message + * The is identical to &p9_stat, but the strings don't point to + * the same memory block and should be freed separately + * + * See Also: http://plan9.bell-labs.com/magic/man2html/2/stat + */ + struct p9_wstat { u16 size; u16 type; @@ -335,10 +504,20 @@ struct p9_twstat { struct p9_rwstat { }; -/* - * fcall is the primary packet structure - * - */ +/** + * struct p9_fcall - primary packet structure + * @size: prefixed length of the structure + * @id: protocol operating identifier of type &p9_msg_t + * @tag: transaction id of the request + * @sdata: payload + * @params: per-operation parameters + * + * &p9_fcall represents the structure for all 9P RPC + * transactions. Requests are packaged into fcalls, and reponses + * must be extracted from them. + * + * See Also: http://plan9.bell-labs.com/magic/man2html/2/fcall + */ struct p9_fcall { u32 size; diff --git a/include/net/9p/client.h b/include/net/9p/client.h index e52f93d..c936dd1 100644 --- a/include/net/9p/client.h +++ b/include/net/9p/client.h @@ -26,6 +26,23 @@ #ifndef NET_9P_CLIENT_H #define NET_9P_CLIENT_H +/** + * struct p9_client - per client instance state + * @lock: protect @fidlist + * @msize: maximum data size negotiated by protocol + * @dotu: extension flags negotiated by protocol + * @trans_mod: module API instantiated with this client + * @trans: tranport instance state and API + * @conn: connection state information used by trans_fd + * @fidpool: fid handle accounting for session + * @fidlist: List of active fid handles + * + * The client structure is used to keep track of various per-client + * state that has been instantiated. + * + * Bugs: duplicated data and potentially unnecessary elements. + */ + struct p9_client { spinlock_t lock; /* protect client structure */ int msize; @@ -38,6 +55,24 @@ struct p9_client { struct list_head fidlist; }; +/** + * struct p9_fid - file system entity handle + * @clnt: back pointer to instantiating &p9_client + * @fid: numeric identifier for this handle + * @mode: current mode of this fid (enum?) + * @qid: the &p9_qid server identifier this handle points to + * @iounit: the server reported maximum transaction size for this file + * @uid: the numeric uid of the local user who owns this handle + * @aux: transport specific information (unused?) + * @rdir_fpos: tracks offset of file position when reading directory contents + * @rdir_pos: (unused?) + * @rdir_fcall: holds response of last directory read request + * @flist: per-client-instance fid tracking + * @dlist: per-dentry fid tracking + * + * TODO: This needs lots of explanation. + */ + struct p9_fid { struct p9_client *clnt; u32 fid; diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index d2209ae..240e0de 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -26,12 +26,40 @@ #ifndef NET_9P_TRANSPORT_H #define NET_9P_TRANSPORT_H +/** + * enum p9_trans_status - different states of underlying transports + * @Connected: transport is connected and healthy + * @Disconnected: transport has been disconnected + * @Hung: transport is connected by wedged + * + * This enumeration details the various states a transport + * instatiation can be in. + */ + enum p9_trans_status { Connected, Disconnected, Hung, }; +/** + * struct p9_trans - per-transport state and API + * @status: transport &p9_trans_status + * @msize: negotiated maximum packet size (duplicate from client) + * @extended: negotiated protocol extensions (duplicate from client) + * @priv: transport private data + * @close: member function to disconnect and close the transport + * @rpc: member function to issue a request to the transport + * + * This is the basic API for a transport instance. It is used as + * a handle by the client to issue requests. This interface is currently + * in flux during reorganization. + * + * Bugs: there is lots of duplicated data here and its not clear that + * the member functions need to be per-instance versus per transport + * module. + */ + struct p9_trans { enum p9_trans_status status; int msize; @@ -42,6 +70,21 @@ struct p9_trans { struct p9_fcall **rc); }; +/** + * struct p9_trans_module - transport module interface + * @list: used to maintain a list of currently available transports + * @name: the human-readable name of the transport + * @maxsize: transport provided maximum packet size + * @def: set if this transport should be considered the default + * @create: member function to create a new connection on this transport + * + * This is the basic API for a transport module which is registered by the + * transport module with the 9P core network module and used by the client + * to instantiate a new connection on a transport. + * + * Bugs: the transport module list isn't protected. + */ + struct p9_trans_module { struct list_head list; char *name; /* name of transport */ diff --git a/net/9p/conv.c b/net/9p/conv.c index 3fe35d5..4454720 100644 --- a/net/9p/conv.c +++ b/net/9p/conv.c @@ -197,7 +197,7 @@ static void buf_get_qid(struct cbuf *bufp, struct p9_qid *qid) /** * p9_size_wstat - calculate the size of a variable length stat struct - * @stat: metadata (stat) structure + * @wstat: metadata (stat) structure * @dotu: non-zero if 9P2000.u * */ @@ -511,6 +511,12 @@ p9_create_common(struct cbuf *bufp, u32 size, u8 id) return fc; } +/** + * p9_set_tag - set the tag field of an &p9_fcall structure + * @fc: fcall structure to set tag within + * @tag: tag id to set + */ + void p9_set_tag(struct p9_fcall *fc, u16 tag) { fc->tag = tag; @@ -518,6 +524,12 @@ void p9_set_tag(struct p9_fcall *fc, u16 tag) } EXPORT_SYMBOL(p9_set_tag); +/** + * p9_create_tversion - allocates and creates a T_VERSION request + * @msize: requested maximum data size + * @version: version string to negotiate + * + */ struct p9_fcall *p9_create_tversion(u32 msize, char *version) { int size; @@ -542,6 +554,16 @@ error: } EXPORT_SYMBOL(p9_create_tversion); +/** + * p9_create_tauth - allocates and creates a T_AUTH request + * @afid: handle to use for authentication protocol + * @uname: user name attempting to authenticate + * @aname: mount specifier for remote server + * @n_uname: numeric id for user attempting to authneticate + * @dotu: 9P2000.u extension flag + * + */ + struct p9_fcall *p9_create_tauth(u32 afid, char *uname, char *aname, u32 n_uname, int dotu) { @@ -580,6 +602,18 @@ error: } EXPORT_SYMBOL(p9_create_tauth); +/** + * p9_create_tattach - allocates and creates a T_ATTACH request + * @fid: handle to use for the new mount point + * @afid: handle to use for authentication protocol + * @uname: user name attempting to attach + * @aname: mount specifier for remote server + * @n_uname: numeric id for user attempting to attach + * @n_uname: numeric id for user attempting to attach + * @dotu: 9P2000.u extension flag + * + */ + struct p9_fcall * p9_create_tattach(u32 fid, u32 afid, char *uname, char *aname, u32 n_uname, int dotu) @@ -616,6 +650,12 @@ error: } EXPORT_SYMBOL(p9_create_tattach); +/** + * p9_create_tflush - allocates and creates a T_FLUSH request + * @oldtag: tag id for the transaction we are attempting to cancel + * + */ + struct p9_fcall *p9_create_tflush(u16 oldtag) { int size; @@ -639,6 +679,15 @@ error: } EXPORT_SYMBOL(p9_create_tflush); +/** + * p9_create_twalk - allocates and creates a T_FLUSH request + * @fid: handle we are traversing from + * @newfid: a new handle for this transaction + * @nwname: number of path elements to traverse + * @wnames: array of path elements + * + */ + struct p9_fcall *p9_create_twalk(u32 fid, u32 newfid, u16 nwname, char **wnames) { @@ -677,6 +726,13 @@ error: } EXPORT_SYMBOL(p9_create_twalk); +/** + * p9_create_topen - allocates and creates a T_OPEN request + * @fid: handle we are trying to open + * @mode: what mode we are trying to open the file in + * + */ + struct p9_fcall *p9_create_topen(u32 fid, u8 mode) { int size; @@ -701,6 +757,19 @@ error: } EXPORT_SYMBOL(p9_create_topen); +/** + * p9_create_tcreate - allocates and creates a T_CREATE request + * @fid: handle of directory we are trying to create in + * @name: name of the file we are trying to create + * @perm: permissions for the file we are trying to create + * @mode: what mode we are trying to open the file in + * @extension: 9p2000.u extension string (for special files) + * @dotu: 9p2000.u enabled flag + * + * Note: Plan 9 create semantics include opening the resulting file + * which is why mode is included. + */ + struct p9_fcall *p9_create_tcreate(u32 fid, char *name, u32 perm, u8 mode, char *extension, int dotu) { @@ -736,6 +805,13 @@ error: } EXPORT_SYMBOL(p9_create_tcreate); +/** + * p9_create_tread - allocates and creates a T_READ request + * @fid: handle of the file we are trying to read + * @offset: offset to start reading from + * @count: how many bytes to read + */ + struct p9_fcall *p9_create_tread(u32 fid, u64 offset, u32 count) { int size; @@ -761,6 +837,17 @@ error: } EXPORT_SYMBOL(p9_create_tread); +/** + * p9_create_twrite - allocates and creates a T_WRITE request from the kernel + * @fid: handle of the file we are trying to write + * @offset: offset to start writing at + * @count: how many bytes to write + * @data: data to write + * + * This function will create a requst with data buffers from the kernel + * such as the page cache. + */ + struct p9_fcall *p9_create_twrite(u32 fid, u64 offset, u32 count, const char *data) { @@ -794,6 +881,16 @@ error: } EXPORT_SYMBOL(p9_create_twrite); +/** + * p9_create_twrite_u - allocates and creates a T_WRITE request from userspace + * @fid: handle of the file we are trying to write + * @offset: offset to start writing at + * @count: how many bytes to write + * @data: data to write + * + * This function will create a request with data buffers from userspace + */ + struct p9_fcall *p9_create_twrite_u(u32 fid, u64 offset, u32 count, const char __user *data) { @@ -827,6 +924,14 @@ error: } EXPORT_SYMBOL(p9_create_twrite_u); +/** + * p9_create_tclunk - allocate a request to forget about a file handle + * @fid: handle of the file we closing or forgetting about + * + * clunk is used both to close open files and to discard transient handles + * which may be created during meta-data operations and hierarchy traversal. + */ + struct p9_fcall *p9_create_tclunk(u32 fid) { int size; @@ -850,6 +955,12 @@ error: } EXPORT_SYMBOL(p9_create_tclunk); +/** + * p9_create_tremove - allocate and create a request to remove a file + * @fid: handle of the file or directory we are removing + * + */ + struct p9_fcall *p9_create_tremove(u32 fid) { int size; @@ -873,6 +984,12 @@ error: } EXPORT_SYMBOL(p9_create_tremove); +/** + * p9_create_tstat - allocate and populate a request for attributes + * @fid: handle of the file or directory we are trying to get the attributes of + * + */ + struct p9_fcall *p9_create_tstat(u32 fid) { int size; @@ -896,6 +1013,14 @@ error: } EXPORT_SYMBOL(p9_create_tstat); +/** + * p9_create_tstat - allocate and populate a request to change attributes + * @fid: handle of the file or directory we are trying to change + * @wstat: &p9_stat structure with attributes we wish to set + * @dotu: 9p2000.u enabled flag + * + */ + struct p9_fcall *p9_create_twstat(u32 fid, struct p9_wstat *wstat, int dotu) { @@ -922,3 +1047,4 @@ error: return fc; } EXPORT_SYMBOL(p9_create_twstat); + diff --git a/net/9p/error.c b/net/9p/error.c index 64104b9..388770c 100644 --- a/net/9p/error.c +++ b/net/9p/error.c @@ -33,6 +33,13 @@ #include #include +/** + * struct errormap - map string errors from Plan 9 to Linux numeric ids + * @name: string sent over 9P + * @val: numeric id most closely representing @name + * @namelen: length of string + * @list: hash-table list for string lookup + */ struct errormap { char *name; int val; @@ -177,8 +184,7 @@ static struct errormap errmap[] = { }; /** - * p9_error_init - preload - * @errstr: error string + * p9_error_init - preload mappings into hash list * */ @@ -206,6 +212,7 @@ EXPORT_SYMBOL(p9_error_init); /** * errstr2errno - convert error string to error number * @errstr: error string + * @len: length of error string * */ diff --git a/net/9p/fcprint.c b/net/9p/fcprint.c index 40244fb..53dd8e2 100644 --- a/net/9p/fcprint.c +++ b/net/9p/fcprint.c @@ -142,6 +142,14 @@ p9_printdata(char *buf, int buflen, u8 *data, int datalen) return p9_dumpdata(buf, buflen, data, datalen < 16?datalen:16); } +/** + * p9_printfcall - decode and print a protocol structure into a buffer + * @buf: buffer to deposit decoded structure into + * @buflen: available space in buffer + * @fc: protocol rpc structure of type &p9_fcall + * @extended: whether or not session is operating with extended protocol + */ + int p9_printfcall(char *buf, int buflen, struct p9_fcall *fc, int extended) { diff --git a/net/9p/mod.c b/net/9p/mod.c index c285aab..c6d9695 100644 --- a/net/9p/mod.c +++ b/net/9p/mod.c @@ -39,9 +39,6 @@ module_param_named(debug, p9_debug_level, uint, 0); MODULE_PARM_DESC(debug, "9P debugging level"); #endif -extern int p9_mux_global_init(void); -extern void p9_mux_global_exit(void); - /* * Dynamic Transport Registration Routines * @@ -52,7 +49,7 @@ static struct p9_trans_module *v9fs_default_transport; /** * v9fs_register_trans - register a new transport with 9p - * @m - structure describing the transport module and entry points + * @m: structure describing the transport module and entry points * */ void v9fs_register_trans(struct p9_trans_module *m) @@ -65,7 +62,7 @@ EXPORT_SYMBOL(v9fs_register_trans); /** * v9fs_match_trans - match transport versus registered transports - * @arg: string identifying transport + * @name: string identifying transport * */ struct p9_trans_module *v9fs_match_trans(const substring_t *name) diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index f624dff..c6eda99 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -47,12 +47,29 @@ #define SCHED_TIMEOUT 10 #define MAXPOLLWADDR 2 +/** + * struct p9_fd_opts - per-transport options + * @rfd: file descriptor for reading (trans=fd) + * @wfd: file descriptor for writing (trans=fd) + * @port: port to connect to (trans=tcp) + * + */ + struct p9_fd_opts { int rfd; int wfd; u16 port; }; + +/** + * struct p9_trans_fd - transport state + * @rd: reference to file to read from + * @wr: reference of file to write to + * @conn: connection state reference + * + */ + struct p9_trans_fd { struct file *rd; struct file *wr; @@ -90,10 +107,24 @@ enum { }; struct p9_req; - typedef void (*p9_conn_req_callback)(struct p9_req *req, void *a); + +/** + * struct p9_req - fd mux encoding of an rpc transaction + * @lock: protects req_list + * @tag: numeric tag for rpc transaction + * @tcall: request &p9_fcall structure + * @rcall: response &p9_fcall structure + * @err: error state + * @cb: callback for when response is received + * @cba: argument to pass to callback + * @flush: flag to indicate RPC has been flushed + * @req_list: list link for higher level objects to chain requests + * + */ + struct p9_req { - spinlock_t lock; /* protect request structure */ + spinlock_t lock; int tag; struct p9_fcall *tcall; struct p9_fcall *rcall; @@ -104,7 +135,39 @@ struct p9_req { struct list_head req_list; }; -struct p9_mux_poll_task; +struct p9_mux_poll_task { + struct task_struct *task; + struct list_head mux_list; + int muxnum; +}; + +/** + * struct p9_conn - fd mux connection state information + * @lock: protects mux_list (?) + * @mux_list: list link for mux to manage multiple connections (?) + * @poll_task: task polling on this connection + * @msize: maximum size for connection (dup) + * @extended: 9p2000.u flag (dup) + * @trans: reference to transport instance for this connection + * @tagpool: id accounting for transactions + * @err: error state + * @equeue: event wait_q (?) + * @req_list: accounting for requests which have been sent + * @unsent_req_list: accounting for requests that haven't been sent + * @rcall: current response &p9_fcall structure + * @rpos: read position in current frame + * @rbuf: current read buffer + * @wpos: write position for current frame + * @wsize: amount of data to write for current frame + * @wbuf: current write buffer + * @poll_wait: array of wait_q's for various worker threads + * @poll_waddr: ???? + * @pt: poll state + * @rq: current read work + * @wq: current write work + * @wsched: ???? + * + */ struct p9_conn { spinlock_t lock; /* protect lock structure */ @@ -132,11 +195,16 @@ struct p9_conn { unsigned long wsched; }; -struct p9_mux_poll_task { - struct task_struct *task; - struct list_head mux_list; - int muxnum; -}; +/** + * struct p9_mux_rpc - fd mux rpc accounting structure + * @m: connection this request was issued on + * @err: error state + * @tcall: request &p9_fcall + * @rcall: response &p9_fcall + * @wqueue: wait queue that client is blocked on for this rpc + * + * Bug: isn't this information duplicated elsewhere like &p9_req + */ struct p9_mux_rpc { struct p9_conn *m; @@ -207,10 +275,12 @@ static void p9_mux_put_tag(struct p9_conn *m, u16 tag) /** * p9_mux_calc_poll_procs - calculates the number of polling procs - * based on the number of mounted v9fs filesystems. + * @muxnum: number of mounts * + * Calculation is based on the number of mounted v9fs filesystems. * The current implementation returns sqrt of the number of mounts. */ + static int p9_mux_calc_poll_procs(int muxnum) { int n; @@ -331,12 +401,11 @@ static void p9_mux_poll_stop(struct p9_conn *m) /** * p9_conn_create - allocate and initialize the per-session mux data - * Creates the polling task if this is the first session. + * @trans: transport structure * - * @trans - transport structure - * @msize - maximum message size - * @extended - extended flag + * Note: Creates the polling task if this is the first session. */ + static struct p9_conn *p9_conn_create(struct p9_trans *trans) { int i, n; @@ -406,7 +475,10 @@ static struct p9_conn *p9_conn_create(struct p9_trans *trans) /** * p9_mux_destroy - cancels all pending requests and frees mux resources + * @m: mux to destroy + * */ + static void p9_conn_destroy(struct p9_conn *m) { P9_DPRINTK(P9_DEBUG_MUX, "mux %p prev %p next %p\n", m, @@ -429,9 +501,14 @@ static void p9_conn_destroy(struct p9_conn *m) } /** - * p9_pollwait - called by files poll operation to add v9fs-poll task - * to files wait queue + * p9_pollwait - add poll task to the wait queue + * @filp: file pointer being polled + * @wait_address: wait_q to block on + * @p: poll state + * + * called by files poll operation to add v9fs-poll task to files wait queue */ + static void p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p) { @@ -462,7 +539,10 @@ p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p) /** * p9_poll_mux - polls a mux and schedules read or write works if necessary + * @m: connection to poll + * */ + static void p9_poll_mux(struct p9_conn *m) { int n; @@ -499,9 +579,14 @@ static void p9_poll_mux(struct p9_conn *m) } /** - * p9_poll_proc - polls all v9fs transports for new events and queues - * the appropriate work to the work queue + * p9_poll_proc - poll worker thread + * @a: thread state and arguments + * + * polls all v9fs transports for new events and queues the appropriate + * work to the work queue + * */ + static int p9_poll_proc(void *a) { struct p9_conn *m, *mtmp; @@ -527,7 +612,10 @@ static int p9_poll_proc(void *a) /** * p9_write_work - called when a transport can send some data + * @work: container for work to be done + * */ + static void p9_write_work(struct work_struct *work) { int n, err; @@ -638,7 +726,10 @@ static void process_request(struct p9_conn *m, struct p9_req *req) /** * p9_read_work - called when there is some data to be read from a transport + * @work: container of work to be done + * */ + static void p9_read_work(struct work_struct *work) { int n, err; @@ -793,7 +884,9 @@ error: * @tc: request to be sent * @cb: callback function to call when response is received * @cba: parameter to pass to the callback function + * */ + static struct p9_req *p9_send_request(struct p9_conn *m, struct p9_fcall *tc, p9_conn_req_callback cb, void *cba) @@ -961,10 +1054,12 @@ p9_conn_rpc_cb(struct p9_req *req, void *a) /** * p9_fd_rpc- sends 9P request and waits until a response is available. * The function can be interrupted. - * @m: mux data + * @t: transport data * @tc: request to be sent * @rc: pointer where a pointer to the response is stored + * */ + int p9_fd_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc) { @@ -1041,8 +1136,10 @@ p9_fd_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc) * @m: mux data * @tc: request to be sent * @cb: callback function to be called when response arrives - * @cba: value to pass to the callback function + * @a: value to pass to the callback function + * */ + int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc, p9_conn_req_callback cb, void *a) { @@ -1065,7 +1162,9 @@ int p9_conn_rpcnb(struct p9_conn *m, struct p9_fcall *tc, * p9_conn_cancel - cancel all pending requests with error * @m: mux data * @err: error code + * */ + void p9_conn_cancel(struct p9_conn *m, int err) { struct p9_req *req, *rtmp; @@ -1099,7 +1198,7 @@ void p9_conn_cancel(struct p9_conn *m, int err) /** * v9fs_parse_options - parse mount options into session structure * @options: options string passed from mount - * @v9ses: existing v9fs session information + * @opts: transport-specific structure to parse options into * */ @@ -1193,11 +1292,12 @@ static int p9_socket_open(struct p9_trans *trans, struct socket *csocket) /** * p9_fd_read- read from a fd - * @v9ses: session information + * @trans: transport instance state * @v: buffer to receive data into * @len: size of receive buffer * */ + static int p9_fd_read(struct p9_trans *trans, void *v, int len) { int ret; @@ -1220,11 +1320,12 @@ static int p9_fd_read(struct p9_trans *trans, void *v, int len) /** * p9_fd_write - write to a socket - * @v9ses: session information + * @trans: transport instance state * @v: buffer to send data from * @len: size of send buffer * */ + static int p9_fd_write(struct p9_trans *trans, void *v, int len) { int ret; @@ -1296,6 +1397,7 @@ end: * @trans: private socket structure * */ + static void p9_fd_close(struct p9_trans *trans) { struct p9_trans_fd *ts; diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index de7a9f5..0bab1f2 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -55,23 +55,69 @@ static int chan_index; #define P9_INIT_MAXTAG 16 -#define REQ_STATUS_IDLE 0 -#define REQ_STATUS_SENT 1 -#define REQ_STATUS_RCVD 2 -#define REQ_STATUS_FLSH 3 + +/** + * enum p9_req_status_t - virtio request status + * @REQ_STATUS_IDLE: request slot unused + * @REQ_STATUS_SENT: request sent to server + * @REQ_STATUS_RCVD: response received from server + * @REQ_STATUS_FLSH: request has been flushed + * + * The @REQ_STATUS_IDLE state is used to mark a request slot as unused + * but use is actually tracked by the idpool structure which handles tag + * id allocation. + * + */ + +enum p9_req_status_t { + REQ_STATUS_IDLE, + REQ_STATUS_SENT, + REQ_STATUS_RCVD, + REQ_STATUS_FLSH, +}; + +/** + * struct p9_req_t - virtio request slots + * @status: status of this request slot + * @wq: wait_queue for the client to block on for this request + * + * The virtio transport uses an array to track outstanding requests + * instead of a list. While this may incurr overhead during initial + * allocation or expansion, it makes request lookup much easier as the + * tag id is a index into an array. (We use tag+1 so that we can accomodate + * the -1 tag for the T_VERSION request). + * This also has the nice effect of only having to allocate wait_queues + * once, instead of constantly allocating and freeing them. Its possible + * other resources could benefit from this scheme as well. + * + */ struct p9_req_t { int status; wait_queue_head_t *wq; }; -/* We keep all per-channel information in a structure. +/** + * struct virtio_chan - per-instance transport information + * @initialized: whether the channel is initialized + * @inuse: whether the channel is in use + * @lock: protects multiple elements within this structure + * @vdev: virtio dev associated with this channel + * @vq: virtio queue associated with this channel + * @tagpool: accounting for tag ids (and request slots) + * @reqs: array of request slots + * @max_tag: current number of request_slots allocated + * @sg: scatter gather list which is used to pack a request (protected?) + * + * We keep all per-channel information in a structure. * This structure is allocated within the devices dev->mem space. * A pointer to the structure will get put in the transport private. + * */ + static struct virtio_chan { - bool initialized; /* channel is initialized */ - bool inuse; /* channel is in use */ + bool initialized; + bool inuse; spinlock_t lock; @@ -86,7 +132,19 @@ static struct virtio_chan { struct scatterlist sg[VIRTQUEUE_NUM]; } channels[MAX_9P_CHAN]; -/* Lookup requests by tag */ +/** + * p9_lookup_tag - Lookup requests by tag + * @c: virtio channel to lookup tag within + * @tag: numeric id for transaction + * + * this is a simple array lookup, but will grow the + * request_slots as necessary to accomodate transaction + * ids which did not previously have a slot. + * + * Bugs: there is currently no upper limit on request slots set + * here, but that should be constrained by the id accounting. + */ + static struct p9_req_t *p9_lookup_tag(struct virtio_chan *c, u16 tag) { /* This looks up the original request by tag so we know which @@ -130,6 +188,15 @@ static unsigned int rest_of_page(void *data) return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE); } +/** + * p9_virtio_close - reclaim resources of a channel + * @trans: transport state + * + * This reclaims a channel by freeing its resources and + * reseting its inuse flag. + * + */ + static void p9_virtio_close(struct p9_trans *trans) { struct virtio_chan *chan = trans->priv; @@ -151,6 +218,19 @@ static void p9_virtio_close(struct p9_trans *trans) kfree(trans); } +/** + * req_done - callback which signals activity from the server + * @vq: virtio queue activity was received on + * + * This notifies us that the server has triggered some activity + * on the virtio channel - most likely a response to request we + * sent. Figure out which requests now have responses and wake up + * those threads. + * + * Bugs: could do with some additional sanity checking, but appears to work. + * + */ + static void req_done(struct virtqueue *vq) { struct virtio_chan *chan = vq->vdev->priv; @@ -169,6 +249,20 @@ static void req_done(struct virtqueue *vq) spin_unlock_irqrestore(&chan->lock, flags); } +/** + * pack_sg_list - pack a scatter gather list from a linear buffer + * @sg: scatter/gather list to pack into + * @start: which segment of the sg_list to start at + * @limit: maximum segment to pack data to + * @data: data to pack into scatter/gather list + * @count: amount of data to pack into the scatter/gather list + * + * sg_lists have multiple segments of various sizes. This will pack + * arbitrary data into an existing scatter gather list, segmenting the + * data as necessary within constraints. + * + */ + static int pack_sg_list(struct scatterlist *sg, int start, int limit, char *data, int count) @@ -189,6 +283,14 @@ pack_sg_list(struct scatterlist *sg, int start, int limit, char *data, return index-start; } +/** + * p9_virtio_rpc - issue a request and wait for a response + * @t: transport state + * @tc: &p9_fcall request to transmit + * @rc: &p9_fcall to put reponse into + * + */ + static int p9_virtio_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc) { @@ -263,6 +365,16 @@ p9_virtio_rpc(struct p9_trans *t, struct p9_fcall *tc, struct p9_fcall **rc) return 0; } +/** + * p9_virtio_probe - probe for existence of 9P virtio channels + * @vdev: virtio device to probe + * + * This probes for existing virtio channels. At present only + * a single channel is in use, so in the future more work may need + * to be done here. + * + */ + static int p9_virtio_probe(struct virtio_device *vdev) { int err; @@ -307,11 +419,28 @@ fail: return err; } -/* This sets up a transport channel for 9p communication. Right now + +/** + * p9_virtio_create - allocate a new virtio channel + * @devname: string identifying the channel to connect to (unused) + * @args: args passed from sys_mount() for per-transport options (unused) + * @msize: requested maximum packet size + * @extended: 9p2000.u enabled flag + * + * This sets up a transport channel for 9p communication. Right now * we only match the first available channel, but eventually we couldlook up * alternate channels by matching devname versus a virtio_config entry. * We use a simple reference count mechanism to ensure that only a single - * mount has a channel open at a time. */ + * mount has a channel open at a time. + * + * Bugs: doesn't allow identification of a specific channel + * to allocate, channels are allocated sequentially. This was + * a pragmatic decision to get things rolling, but ideally some + * way of identifying the channel to attach to would be nice + * if we are going to support multiple channels. + * + */ + static struct p9_trans * p9_virtio_create(const char *devname, char *args, int msize, unsigned char extended) @@ -360,6 +489,12 @@ p9_virtio_create(const char *devname, char *args, int msize, return trans; } +/** + * p9_virtio_remove - clean up resources associated with a virtio device + * @vdev: virtio device to remove + * + */ + static void p9_virtio_remove(struct virtio_device *vdev) { struct virtio_chan *chan = vdev->priv; diff --git a/net/9p/util.c b/net/9p/util.c index ef72155..4d56460 100644 --- a/net/9p/util.c +++ b/net/9p/util.c @@ -32,11 +32,23 @@ #include #include +/** + * struct p9_idpool - per-connection accounting for tag idpool + * @lock: protects the pool + * @pool: idr to allocate tag id from + * + */ + struct p9_idpool { spinlock_t lock; struct idr pool; }; +/** + * p9_idpool_create - create a new per-connection id pool + * + */ + struct p9_idpool *p9_idpool_create(void) { struct p9_idpool *p; @@ -52,6 +64,11 @@ struct p9_idpool *p9_idpool_create(void) } EXPORT_SYMBOL(p9_idpool_create); +/** + * p9_idpool_destroy - create a new per-connection id pool + * @p: idpool to destory + */ + void p9_idpool_destroy(struct p9_idpool *p) { idr_destroy(&p->pool); @@ -61,9 +78,9 @@ EXPORT_SYMBOL(p9_idpool_destroy); /** * p9_idpool_get - allocate numeric id from pool - * @p - pool to allocate from + * @p: pool to allocate from * - * XXX - This seems to be an awful generic function, should it be in idr.c with + * Bugs: This seems to be an awful generic function, should it be in idr.c with * the lock included in struct idr? */ @@ -94,9 +111,10 @@ EXPORT_SYMBOL(p9_idpool_get); /** * p9_idpool_put - release numeric id from pool - * @p - pool to allocate from + * @id: numeric id which is being released + * @p: pool to release id into * - * XXX - This seems to be an awful generic function, should it be in idr.c with + * Bugs: This seems to be an awful generic function, should it be in idr.c with * the lock included in struct idr? */ @@ -111,11 +129,13 @@ EXPORT_SYMBOL(p9_idpool_put); /** * p9_idpool_check - check if the specified id is available - * @id - id to check - * @p - pool + * @id: id to check + * @p: pool to check */ + int p9_idpool_check(int id, struct p9_idpool *p) { return idr_find(&p->pool, id) != NULL; } EXPORT_SYMBOL(p9_idpool_check); + -- cgit v1.1 From ab31267dfeddf80b2e483f077c8b03905993722b Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Thu, 6 Mar 2008 17:10:28 -0600 Subject: fs/9p/v9fs.c (v9fs_parse_options): Handle kstrdup and match_strdup failure. Now that this function can fail, return an int, diagnose other option-parsing failures, and adjust the sole caller: (v9fs_session_init): Handle kstrdup failure. Propagate any new v9fs_parse_options failure "up". Signed-off-by: Jim Meyering Cc: Ron Minnich Cc: Latchesar Ionkov Signed-off-by: Andrew Morton Acked-by: Eric Van Hensbergen --- fs/9p/v9fs.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 79d310c..5c1ccaf 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -73,16 +73,17 @@ static match_table_t tokens = { * v9fs_parse_options - parse mount options into session structure * @v9ses: existing v9fs session information * + * Return 0 upon success, -ERRNO upon failure. */ -static void v9fs_parse_options(struct v9fs_session_info *v9ses) +static int v9fs_parse_options(struct v9fs_session_info *v9ses) { char *options; substring_t args[MAX_OPT_ARGS]; char *p; int option = 0; char *s, *e; - int ret; + int ret = 0; /* setup defaults */ v9ses->afid = ~0; @@ -90,19 +91,26 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses) v9ses->cache = 0; if (!v9ses->options) - return; + return 0; options = kstrdup(v9ses->options, GFP_KERNEL); + if (!options) { + P9_DPRINTK(P9_DEBUG_ERROR, + "failed to allocate copy of option string\n"); + return -ENOMEM; + } + while ((p = strsep(&options, ",")) != NULL) { int token; if (!*p) continue; token = match_token(p, tokens, args); if (token < Opt_uname) { - ret = match_int(&args[0], &option); - if (ret < 0) { + int r = match_int(&args[0], &option); + if (r < 0) { P9_DPRINTK(P9_DEBUG_ERROR, "integer field, but no integer?\n"); + ret = r; continue; } } @@ -138,6 +146,13 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses) case Opt_access: s = match_strdup(&args[0]); + if (!s) { + P9_DPRINTK(P9_DEBUG_ERROR, + "failed to allocate copy" + " of option argument\n"); + ret = -ENOMEM; + break; + } v9ses->flags &= ~V9FS_ACCESS_MASK; if (strcmp(s, "user") == 0) v9ses->flags |= V9FS_ACCESS_USER; @@ -157,6 +172,7 @@ static void v9fs_parse_options(struct v9fs_session_info *v9ses) } } kfree(options); + return ret; } /** @@ -172,6 +188,7 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, { int retval = -EINVAL; struct p9_fid *fid; + int rc; v9ses->uname = __getname(); if (!v9ses->uname) @@ -190,7 +207,18 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, v9ses->dfltuid = V9FS_DEFUID; v9ses->dfltgid = V9FS_DEFGID; v9ses->options = kstrdup(data, GFP_KERNEL); - v9fs_parse_options(v9ses); + if (!v9ses->options) { + P9_DPRINTK(P9_DEBUG_ERROR, + "failed to allocate copy of option string\n"); + retval = -ENOMEM; + goto error; + } + + rc = v9fs_parse_options(v9ses); + if (rc < 0) { + retval = rc; + goto error; + } v9ses->clnt = p9_client_create(dev_name, v9ses->options); -- cgit v1.1 From bb8ffdfc3e3b32ad9fcdb8da289088d3b22794e5 Mon Sep 17 00:00:00 2001 From: Eric Van Hensbergen Date: Fri, 7 Mar 2008 10:53:53 -0600 Subject: 9p: propagate parse_option changes to client and transports Propagate changes that were made to the parse_options code to the other parse options pieces present in the other modules. Looks like the client parse options was probably corrupting the parse string and causing problems for others. Signed-off-by: Eric Van Hensbergen --- net/9p/client.c | 30 +++++++++++++++++++++++------- net/9p/trans_fd.c | 29 ++++++++++++++++++++++------- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/net/9p/client.c b/net/9p/client.c index 84e087e..553c34e 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -64,21 +64,30 @@ static match_table_t tokens = { * @options: options string passed from mount * @v9ses: existing v9fs session information * + * Return 0 upon success, -ERRNO upon failure */ -static void parse_opts(char *options, struct p9_client *clnt) +static int parse_opts(char *opts, struct p9_client *clnt) { + char *options; char *p; substring_t args[MAX_OPT_ARGS]; int option; - int ret; + int ret = 0; clnt->trans_mod = v9fs_default_trans(); clnt->dotu = 1; clnt->msize = 8192; - if (!options) - return; + if (!opts) + return 0; + + options = kstrdup(opts, GFP_KERNEL); + if (!options) { + P9_DPRINTK(P9_DEBUG_ERROR, + "failed to allocate copy of option string\n"); + return -ENOMEM; + } while ((p = strsep(&options, ",")) != NULL) { int token; @@ -86,10 +95,11 @@ static void parse_opts(char *options, struct p9_client *clnt) continue; token = match_token(p, tokens, args); if (token < Opt_trans) { - ret = match_int(&args[0], &option); - if (ret < 0) { + int r = match_int(&args[0], &option); + if (r < 0) { P9_DPRINTK(P9_DEBUG_ERROR, "integer field, but no integer?\n"); + ret = r; continue; } } @@ -107,6 +117,8 @@ static void parse_opts(char *options, struct p9_client *clnt) continue; } } + kfree(options); + return ret; } @@ -138,6 +150,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) if (!clnt) return ERR_PTR(-ENOMEM); + clnt->trans = NULL; spin_lock_init(&clnt->lock); INIT_LIST_HEAD(&clnt->fidlist); clnt->fidpool = p9_idpool_create(); @@ -147,7 +160,10 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) goto error; } - parse_opts(options, clnt); + err = parse_opts(options, clnt); + if (err < 0) + goto error; + if (clnt->trans_mod == NULL) { err = -EPROTONOSUPPORT; P9_DPRINTK(P9_DEBUG_ERROR, diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index c6eda99..97b103b 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -1196,35 +1196,46 @@ void p9_conn_cancel(struct p9_conn *m, int err) } /** - * v9fs_parse_options - parse mount options into session structure + * parse_options - parse mount options into session structure * @options: options string passed from mount * @opts: transport-specific structure to parse options into * + * Returns 0 upon success, -ERRNO upon failure */ -static void parse_opts(char *options, struct p9_fd_opts *opts) +static int parse_opts(char *params, struct p9_fd_opts *opts) { char *p; substring_t args[MAX_OPT_ARGS]; int option; + char *options; int ret; opts->port = P9_PORT; opts->rfd = ~0; opts->wfd = ~0; - if (!options) - return; + if (!params) + return 0; + + options = kstrdup(params, GFP_KERNEL); + if (!options) { + P9_DPRINTK(P9_DEBUG_ERROR, + "failed to allocate copy of option string\n"); + return -ENOMEM; + } while ((p = strsep(&options, ",")) != NULL) { int token; + int r; if (!*p) continue; token = match_token(p, tokens, args); - ret = match_int(&args[0], &option); - if (ret < 0) { + r = match_int(&args[0], &option); + if (r < 0) { P9_DPRINTK(P9_DEBUG_ERROR, "integer field, but no integer?\n"); + ret = r; continue; } switch (token) { @@ -1241,6 +1252,8 @@ static void parse_opts(char *options, struct p9_fd_opts *opts) continue; } } + kfree(options); + return 0; } static int p9_fd_open(struct p9_trans *trans, int rfd, int wfd) @@ -1430,7 +1443,9 @@ p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu) struct p9_fd_opts opts; struct p9_trans_fd *p; - parse_opts(args, &opts); + err = parse_opts(args, &opts); + if (err < 0) + return ERR_PTR(err); csocket = NULL; trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL); -- cgit v1.1 From c1549497e903a1ffa1c5808337a987180e480e7a Mon Sep 17 00:00:00 2001 From: Josef 'Jeff' Sipek Date: Fri, 7 Mar 2008 11:39:13 -0600 Subject: 9p: use struct mutex instead of struct semaphore Replace semaphores protecting use flags with a mutex. Signed-off-by: Josef 'Jeff' Sipek Acked-by: Eric Van Hensbergen --- net/9p/trans_virtio.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index 0bab1f2..d23ed60 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -49,7 +49,7 @@ #define VIRTQUEUE_NUM 128 /* a single mutex to manage channel initialization and attachment */ -static DECLARE_MUTEX(virtio_9p_lock); +static DEFINE_MUTEX(virtio_9p_lock); /* global which tracks highest initialized channel */ static int chan_index; @@ -211,9 +211,9 @@ static void p9_virtio_close(struct p9_trans *trans) chan->max_tag = 0; spin_unlock_irqrestore(&chan->lock, flags); - down(&virtio_9p_lock); + mutex_lock(&virtio_9p_lock); chan->inuse = false; - up(&virtio_9p_lock); + mutex_unlock(&virtio_9p_lock); kfree(trans); } @@ -381,10 +381,10 @@ static int p9_virtio_probe(struct virtio_device *vdev) struct virtio_chan *chan; int index; - down(&virtio_9p_lock); + mutex_lock(&virtio_9p_lock); index = chan_index++; chan = &channels[index]; - up(&virtio_9p_lock); + mutex_unlock(&virtio_9p_lock); if (chan_index > MAX_9P_CHAN) { printk(KERN_ERR "9p: virtio: Maximum channels exceeded\n"); @@ -413,9 +413,9 @@ static int p9_virtio_probe(struct virtio_device *vdev) out_free_vq: vdev->config->del_vq(chan->vq); fail: - down(&virtio_9p_lock); + mutex_lock(&virtio_9p_lock); chan_index--; - up(&virtio_9p_lock); + mutex_unlock(&virtio_9p_lock); return err; } @@ -449,7 +449,7 @@ p9_virtio_create(const char *devname, char *args, int msize, struct virtio_chan *chan = channels; int index = 0; - down(&virtio_9p_lock); + mutex_lock(&virtio_9p_lock); while (index < MAX_9P_CHAN) { if (chan->initialized && !chan->inuse) { chan->inuse = true; @@ -459,7 +459,7 @@ p9_virtio_create(const char *devname, char *args, int msize, chan = &channels[index]; } } - up(&virtio_9p_lock); + mutex_unlock(&virtio_9p_lock); if (index >= MAX_9P_CHAN) { printk(KERN_ERR "9p: no channels available\n"); -- cgit v1.1 From 728fc4ef17748042d9c71144aa339ed9c68e8b01 Mon Sep 17 00:00:00 2001 From: Josef 'Jeff' Sipek Date: Fri, 7 Mar 2008 11:40:33 -0600 Subject: 9p: Correct fidpool creation failure in p9_client_create On error, p9_idpool_create returns an ERR_PTR-encoded errno. Signed-off-by: Josef 'Jeff' Sipek Acked-by: Eric Van Hensbergen --- net/9p/client.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/9p/client.c b/net/9p/client.c index 553c34e..2ffe40c 100644 --- a/net/9p/client.c +++ b/net/9p/client.c @@ -154,7 +154,7 @@ struct p9_client *p9_client_create(const char *dev_name, char *options) spin_lock_init(&clnt->lock); INIT_LIST_HEAD(&clnt->fidlist); clnt->fidpool = p9_idpool_create(); - if (!clnt->fidpool) { + if (IS_ERR(clnt->fidpool)) { err = PTR_ERR(clnt->fidpool); clnt->fidpool = NULL; goto error; -- cgit v1.1 From d0c447180bfcb1db8d59e6ddb10f0346bd7d29e9 Mon Sep 17 00:00:00 2001 From: Steven Rostedt Date: Sat, 3 May 2008 17:29:50 -0500 Subject: 9p: fix flags length in net Some files in the net/9p directory uses "int" for flags. This can cause hard to find bugs on some architectures. This patch converts the flags to use "long" instead. This bug was discovered by doing an allyesconfig make on the -rt kernel where checks are done to ensure all flags are of size sizeof(long). Signed-off-by: Steven Rostedt Acked-by: Eric Van Hensbergen --- net/9p/trans_virtio.c | 2 +- net/9p/util.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index d23ed60..42adc05 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c @@ -201,7 +201,7 @@ static void p9_virtio_close(struct p9_trans *trans) { struct virtio_chan *chan = trans->priv; int count; - unsigned int flags; + unsigned long flags; spin_lock_irqsave(&chan->lock, flags); p9_idpool_destroy(chan->tagpool); diff --git a/net/9p/util.c b/net/9p/util.c index 4d56460..958fc58 100644 --- a/net/9p/util.c +++ b/net/9p/util.c @@ -88,7 +88,7 @@ int p9_idpool_get(struct p9_idpool *p) { int i = 0; int error; - unsigned int flags; + unsigned long flags; retry: if (idr_pre_get(&p->pool, GFP_KERNEL) == 0) @@ -120,7 +120,7 @@ EXPORT_SYMBOL(p9_idpool_get); void p9_idpool_put(int id, struct p9_idpool *p) { - unsigned int flags; + unsigned long flags; spin_lock_irqsave(&p->lock, flags); idr_remove(&p->pool, id); spin_unlock_irqrestore(&p->lock, flags); -- cgit v1.1 From 332c421e67045343de74e644cdf389f559f0d83f Mon Sep 17 00:00:00 2001 From: Eric Van Hensbergen Date: Sat, 3 May 2008 17:29:26 -0500 Subject: 9p: make cryptic unknown error from server less scary Right now when we get an error string from the server that we can't map we report a cryptic error that actually makes it look like we are reporting a problem with the client. This changes the text of the log message to clarify where the error is coming from. Signed-off-by: Eric Van Hensbergen --- net/9p/error.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/9p/error.c b/net/9p/error.c index 388770c..fdebe43 100644 --- a/net/9p/error.c +++ b/net/9p/error.c @@ -237,8 +237,8 @@ int p9_errstr2errno(char *errstr, int len) if (errno == 0) { /* TODO: if error isn't found, add it dynamically */ errstr[len] = 0; - printk(KERN_ERR "%s: errstr :%s: not found\n", __func__, - errstr); + printk(KERN_ERR "%s: server reported unknown error %s\n", + __func__, errstr); errno = 1; } -- cgit v1.1 From 887b3ece65be7b643dfdae0d433c91a26a3f437d Mon Sep 17 00:00:00 2001 From: Eric Van Hensbergen Date: Thu, 8 May 2008 20:26:37 -0500 Subject: 9p: fix error path during early mount There was some cleanup issues during early mount which would trigger a kernel bug for certain types of failure. This patch reorganizes the cleanup to get rid of the bad behavior. This also merges the 9pnet and 9pnet_fd modules for the purpose of configuration and initialization. Keeping the fd transport separate from the core 9pnet code seemed like a good idea at the time, but in practice has caused more harm and confusion than good. Signed-off-by: Eric Van Hensbergen --- fs/9p/v9fs.c | 13 +++++++------ fs/9p/vfs_super.c | 34 ++++++++++++++++------------------ include/net/9p/9p.h | 1 + include/net/9p/transport.h | 1 - net/9p/Kconfig | 10 ---------- net/9p/Makefile | 3 --- net/9p/mod.c | 1 + net/9p/trans_fd.c | 29 ++++++++++++++++++++++------- 8 files changed, 47 insertions(+), 45 deletions(-) diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c index 5c1ccaf..047c791 100644 --- a/fs/9p/v9fs.c +++ b/fs/9p/v9fs.c @@ -206,12 +206,14 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, v9ses->uid = ~0; v9ses->dfltuid = V9FS_DEFUID; v9ses->dfltgid = V9FS_DEFGID; - v9ses->options = kstrdup(data, GFP_KERNEL); - if (!v9ses->options) { - P9_DPRINTK(P9_DEBUG_ERROR, + if (data) { + v9ses->options = kstrdup(data, GFP_KERNEL); + if (!v9ses->options) { + P9_DPRINTK(P9_DEBUG_ERROR, "failed to allocate copy of option string\n"); - retval = -ENOMEM; - goto error; + retval = -ENOMEM; + goto error; + } } rc = v9fs_parse_options(v9ses); @@ -260,7 +262,6 @@ struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, return fid; error: - v9fs_session_close(v9ses); return ERR_PTR(retval); } diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index ba10f17..bf59c39 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -128,29 +128,26 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, fid = v9fs_session_init(v9ses, dev_name, data); if (IS_ERR(fid)) { retval = PTR_ERR(fid); - fid = NULL; - kfree(v9ses); - v9ses = NULL; - goto error; + goto close_session; } st = p9_client_stat(fid); if (IS_ERR(st)) { retval = PTR_ERR(st); - goto error; + goto clunk_fid; } sb = sget(fs_type, NULL, v9fs_set_super, v9ses); if (IS_ERR(sb)) { retval = PTR_ERR(sb); - goto error; + goto free_stat; } v9fs_fill_super(sb, v9ses, flags); inode = v9fs_get_inode(sb, S_IFDIR | mode); if (IS_ERR(inode)) { retval = PTR_ERR(inode); - goto error; + goto release_sb; } inode->i_uid = uid; @@ -159,7 +156,7 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, root = d_alloc_root(inode); if (!root) { retval = -ENOMEM; - goto error; + goto release_sb; } sb->s_root = root; @@ -170,21 +167,22 @@ static int v9fs_get_sb(struct file_system_type *fs_type, int flags, return simple_set_mnt(mnt, sb); -error: - kfree(st); - if (fid) - p9_client_clunk(fid); - - if (v9ses) { - v9fs_session_close(v9ses); - kfree(v9ses); - } - +release_sb: if (sb) { up_write(&sb->s_umount); deactivate_super(sb); } +free_stat: + kfree(st); + +clunk_fid: + p9_client_clunk(fid); + +close_session: + v9fs_session_close(v9ses); + kfree(v9ses); + return retval; } diff --git a/include/net/9p/9p.h b/include/net/9p/9p.h index 7bfb2f2..b3d3e27 100644 --- a/include/net/9p/9p.h +++ b/include/net/9p/9p.h @@ -595,4 +595,5 @@ int p9_idpool_check(int id, struct p9_idpool *p); int p9_error_init(void); int p9_errstr2errno(char *, int); +int p9_trans_fd_init(void); #endif /* NET_9P_H */ diff --git a/include/net/9p/transport.h b/include/net/9p/transport.h index 240e0de..0db3a40 100644 --- a/include/net/9p/transport.h +++ b/include/net/9p/transport.h @@ -96,5 +96,4 @@ struct p9_trans_module { void v9fs_register_trans(struct p9_trans_module *m); struct p9_trans_module *v9fs_match_trans(const substring_t *name); struct p9_trans_module *v9fs_default_trans(void); - #endif /* NET_9P_TRANSPORT_H */ diff --git a/net/9p/Kconfig b/net/9p/Kconfig index bafc50c..ff34c5a 100644 --- a/net/9p/Kconfig +++ b/net/9p/Kconfig @@ -13,16 +13,6 @@ menuconfig NET_9P If unsure, say N. -config NET_9P_FD - depends on NET_9P - default y if NET_9P - tristate "9P File Descriptor Transports (Experimental)" - help - This builds support for file descriptor transports for 9p - which includes support for TCP/IP, named pipes, or passed - file descriptors. TCP/IP is the default transport for 9p, - so if you are going to use 9p, you'll likely want this. - config NET_9P_VIRTIO depends on NET_9P && EXPERIMENTAL && VIRTIO tristate "9P Virtio Transport (Experimental)" diff --git a/net/9p/Makefile b/net/9p/Makefile index 8a10511..5192194 100644 --- a/net/9p/Makefile +++ b/net/9p/Makefile @@ -1,5 +1,4 @@ obj-$(CONFIG_NET_9P) := 9pnet.o -obj-$(CONFIG_NET_9P_FD) += 9pnet_fd.o obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o 9pnet-objs := \ @@ -9,8 +8,6 @@ obj-$(CONFIG_NET_9P_VIRTIO) += 9pnet_virtio.o error.o \ fcprint.o \ util.o \ - -9pnet_fd-objs := \ trans_fd.o \ 9pnet_virtio-objs := \ diff --git a/net/9p/mod.c b/net/9p/mod.c index c6d9695..bdee1fb 100644 --- a/net/9p/mod.c +++ b/net/9p/mod.c @@ -107,6 +107,7 @@ static int __init init_p9(void) p9_error_init(); printk(KERN_INFO "Installing 9P2000 support\n"); + p9_trans_fd_init(); return ret; } diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 97b103b..4507f74 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c @@ -1433,6 +1433,23 @@ static void p9_fd_close(struct p9_trans *trans) kfree(ts); } +/* + * stolen from NFS - maybe should be made a generic function? + */ +static inline int valid_ipaddr4(const char *buf) +{ + int rc, count, in[4]; + + rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]); + if (rc != 4) + return -EINVAL; + for (count = 0; count < 4; count++) { + if (in[count] > 255) + return -EINVAL; + } + return 0; +} + static struct p9_trans * p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu) { @@ -1447,6 +1464,9 @@ p9_trans_create_tcp(const char *addr, char *args, int msize, unsigned char dotu) if (err < 0) return ERR_PTR(err); + if (valid_ipaddr4(addr) < 0) + return ERR_PTR(-EINVAL); + csocket = NULL; trans = kmalloc(sizeof(struct p9_trans), GFP_KERNEL); if (!trans) @@ -1625,7 +1645,7 @@ static struct p9_trans_module p9_fd_trans = { .create = p9_trans_create_fd, }; -static int __init p9_trans_fd_init(void) +int p9_trans_fd_init(void) { int ret = p9_mux_global_init(); if (ret) { @@ -1639,9 +1659,4 @@ static int __init p9_trans_fd_init(void) return 0; } - -module_init(p9_trans_fd_init); - -MODULE_AUTHOR("Latchesar Ionkov "); -MODULE_AUTHOR("Eric Van Hensbergen "); -MODULE_LICENSE("GPL"); +EXPORT_SYMBOL(p9_trans_fd_init); -- cgit v1.1 From 57cc097931e2d28a27e19515c549dc301ba6b6b2 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 14 May 2008 16:05:29 -0700 Subject: mpc5200_psc_spi: typo fix in header block Signed-off-by: Grant Likely Acked-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/mpc52xx_psc_spi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c index 90729469..681d623 100644 --- a/drivers/spi/mpc52xx_psc_spi.c +++ b/drivers/spi/mpc52xx_psc_spi.c @@ -1,5 +1,5 @@ /* - * MPC52xx SPC in SPI mode driver. + * MPC52xx PSC in SPI mode driver. * * Maintainer: Dragos Carp * -- cgit v1.1 From f7c5a770e6006ae2b5f4fd0491565b69e4d4bb48 Mon Sep 17 00:00:00 2001 From: Sebastian Siewior Date: Wed, 14 May 2008 16:05:30 -0700 Subject: m68knommu: add info about removing mcfserial Schedule a removal for this driver. Alternative driver is available for a while now. Signed-off-by: Sebastian Siewior Acked-by: Greg Ungerer Acked-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 8 ++++++++ drivers/serial/Kconfig | 6 +++++- drivers/serial/mcfserial.c | 1 + 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 3c35d45..5b3f31f 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -289,6 +289,14 @@ Who: Glauber Costa --------------------------- +What: old style serial driver for ColdFire (CONFIG_SERIAL_COLDFIRE) +When: 2.6.28 +Why: This driver still uses the old interface and has been replaced + by CONFIG_SERIAL_MCF. +Who: Sebastian Siewior + +--------------------------- + What: /sys/o2cb symlink When: January 2010 Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 36acbcc..62e6eb1 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -976,11 +976,15 @@ config SERIAL_68328_RTS_CTS depends on SERIAL_68328 config SERIAL_COLDFIRE - bool "ColdFire serial support" + bool "ColdFire serial support (DEPRECATED)" depends on COLDFIRE help This driver supports the built-in serial ports of the Motorola ColdFire family of CPUs. + This driver is deprecated because it supports only the old interface + for serial drivers and features like magic keys are not working. + Please switch to the new style driver because this driver will be + removed soon. config SERIAL_MCF bool "Coldfire serial support (new style driver)" diff --git a/drivers/serial/mcfserial.c b/drivers/serial/mcfserial.c index 43af40d..56007cc 100644 --- a/drivers/serial/mcfserial.c +++ b/drivers/serial/mcfserial.c @@ -1,3 +1,4 @@ +#warning This driver is deprecated. Check Kconfig for details. /* * mcfserial.c -- serial driver for ColdFire internal UARTS. * -- cgit v1.1 From 8b8b498836942c0c855333d357d121c0adeefbd9 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 14 May 2008 16:05:31 -0700 Subject: oprofile: don't request cache line alignment for cpu_buffer Alignment was previously requested because cpu_buffer was an [NR_CPUS] array, to avoid cache line sharing between CPUS. After commit 608dfddd845da5ab6accef70154c8910529699f7 (oprofile: change cpu_buffer from array to per_cpu variable ), we dont need to force an alignement anymore since cpu_buffer sits in per_cpu zone. Signed-off-by: Eric Dumazet Cc: Mike Travis Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/oprofile/cpu_buffer.c | 2 +- drivers/oprofile/cpu_buffer.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index efcbf4b..2450b3a3 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -27,7 +27,7 @@ #include "buffer_sync.h" #include "oprof.h" -DEFINE_PER_CPU_SHARED_ALIGNED(struct oprofile_cpu_buffer, cpu_buffer); +DEFINE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer); static void wq_sync_buffer(struct work_struct *work); diff --git a/drivers/oprofile/cpu_buffer.h b/drivers/oprofile/cpu_buffer.h index 1358817..c3e366b 100644 --- a/drivers/oprofile/cpu_buffer.h +++ b/drivers/oprofile/cpu_buffer.h @@ -46,7 +46,7 @@ struct oprofile_cpu_buffer { unsigned long sample_invalid_eip; int cpu; struct delayed_work work; -} ____cacheline_aligned; +}; DECLARE_PER_CPU(struct oprofile_cpu_buffer, cpu_buffer); -- cgit v1.1 From 82f55af06af3d9c478292281ac37b48d2c43741e Mon Sep 17 00:00:00 2001 From: Jens Rottmann Date: Wed, 14 May 2008 16:05:32 -0700 Subject: fix "lxfb: extend PLL table to support dotclocks below 25 MHz" The following patch caused a regression with OLPC panels: commit 3888d4639e78802c4ec1086127124e890461b9e4 lxfb: extend PLL table to support dotclocks below 25 MHz Extends the PLL frequency table of the AMD Geode-LX frame buffer driver to make use of the DIV4 bit, thus adding support for dotclocks between 6 and 25 MHz. These are needed for small LCDs (e.g. 320x240). Also inserts some intermediate steps between pre-existing frequencies. The problem was the insertion of intermediate steps into the frequency table; they would cause the wrong frequency to be matched. This patch drops those intermediate frequencies while keeping the sub-25MHz frequencies. Signed-off-by: Andres Salomon Signed-off-by: Jens Rottmann Tested-by: Andres Salomon Acked-by: Jordan Crouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/geode/lxfb_ops.c | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c index cd9d4cc..aaef916 100644 --- a/drivers/video/geode/lxfb_ops.c +++ b/drivers/video/geode/lxfb_ops.c @@ -63,54 +63,32 @@ static const struct { { 0x00014284, 19688 }, { 0x00011104, 20400 }, { 0x00016363, 23625 }, - { 0x00015303, 24380 }, { 0x000031AC, 24923 }, { 0x0000215D, 25175 }, { 0x00001087, 27000 }, { 0x0000216C, 28322 }, { 0x0000218D, 28560 }, - { 0x00010041, 29913 }, { 0x000010C9, 31200 }, { 0x00003147, 31500 }, - { 0x000141A1, 32400 }, { 0x000010A7, 33032 }, - { 0x00012182, 33375 }, - { 0x000141B1, 33750 }, { 0x00002159, 35112 }, { 0x00004249, 35500 }, { 0x00000057, 36000 }, - { 0x000141E1, 37125 }, { 0x0000219A, 37889 }, { 0x00002158, 39168 }, { 0x00000045, 40000 }, - { 0x000131A1, 40500 }, - { 0x00010061, 42301 }, { 0x00000089, 43163 }, - { 0x00012151, 43875 }, { 0x000010E7, 44900 }, { 0x00002136, 45720 }, - { 0x000152E1, 47250 }, - { 0x00010071, 48000 }, { 0x00003207, 49500 }, { 0x00002187, 50000 }, - { 0x00014291, 50625 }, - { 0x00011101, 51188 }, - { 0x00017481, 54563 }, { 0x00004286, 56250 }, - { 0x00014170, 57375 }, - { 0x00016210, 58500 }, { 0x000010E5, 60065 }, - { 0x00013140, 62796 }, { 0x00004214, 65000 }, - { 0x00016250, 65250 }, { 0x00001105, 68179 }, - { 0x000141C0, 69600 }, - { 0x00015220, 70160 }, - { 0x00010050, 72000 }, { 0x000031E4, 74250 }, { 0x00003183, 75000 }, { 0x00004284, 78750 }, - { 0x00012130, 80052 }, { 0x00001104, 81600 }, { 0x00006363, 94500 }, { 0x00005303, 97520 }, -- cgit v1.1 From 726a7a3d17f183bd0f93daff4d56953c6af78c57 Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Wed, 14 May 2008 16:05:33 -0700 Subject: pnp: clean up pnp_fixup_device() Make it look a bit more like pci_fixup_device/pci_do_fixups. Also print the PnP ID and delete the () from the "foo+0x0/0x1234()". Signed-off-by: Rene Herman Tested-by: Uwe Bugla Acked-by: Uwe Bugla Acked-by: Bjorn Helgaas Cc: Takashi Iwai Cc: Len Brown Signed-off-by: Linus Torvalds --- drivers/pnp/quirks.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index d049a22..a1af2f9 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -212,20 +212,16 @@ static struct pnp_fixup pnp_fixups[] = { void pnp_fixup_device(struct pnp_dev *dev) { - int i = 0; - void (*quirk)(struct pnp_dev *); - - while (*pnp_fixups[i].id) { - if (compare_pnp_id(dev->id, pnp_fixups[i].id)) { - quirk = pnp_fixups[i].quirk_function; + struct pnp_fixup *f; + for (f = pnp_fixups; *f->id; f++) { + if (!compare_pnp_id(dev->id, f->id)) + continue; #ifdef DEBUG - dev_dbg(&dev->dev, "calling "); - print_fn_descriptor_symbol("%s()\n", - (unsigned long) *quirk); + dev_dbg(&dev->dev, "%s: calling ", f->id); + print_fn_descriptor_symbol("%s\n", + (unsigned long) f->quirk_function); #endif - (*quirk)(dev); - } - i++; + f->quirk_function(dev); } } -- cgit v1.1 From bc033c9b5fd261855278f4ed82c3713cc549afbe Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Wed, 14 May 2008 16:05:34 -0700 Subject: pnp: add pnp_build_option() to the API The subsequent AD181x quirk patch would like this as part of the API. pnp_register_dependent_option() adds to the same dependent chain the quirk is walking which is fairly unclean. This enables a private option chain build which it can then just add onto the end when done. Signed-off-by: Rene Herman Tested-by: Uwe Bugla Acked-by: Uwe Bugla Acked-by: Bjorn Helgaas Cc: Takashi Iwai Cc: Len Brown Signed-off-by: Linus Torvalds --- drivers/pnp/base.h | 1 + drivers/pnp/resource.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/pnp/base.h b/drivers/pnp/base.h index 4fe7c58..886dac8 100644 --- a/drivers/pnp/base.h +++ b/drivers/pnp/base.h @@ -19,6 +19,7 @@ void pnp_remove_card(struct pnp_card *card); int pnp_add_card_device(struct pnp_card *card, struct pnp_dev *dev); void pnp_remove_card_device(struct pnp_dev *dev); +struct pnp_option *pnp_build_option(int priority); struct pnp_option *pnp_register_independent_option(struct pnp_dev *dev); struct pnp_option *pnp_register_dependent_option(struct pnp_dev *dev, int priority); diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 2041620..390b500 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -28,7 +28,7 @@ static int pnp_reserve_mem[16] = {[0 ... 15] = -1 }; /* reserve (don't use) some * option registration */ -static struct pnp_option *pnp_build_option(int priority) +struct pnp_option *pnp_build_option(int priority) { struct pnp_option *option = pnp_alloc(sizeof(struct pnp_option)); -- cgit v1.1 From 3b73a223661ed137c5d3d2635f954382e94f5a43 Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Wed, 14 May 2008 16:05:36 -0700 Subject: pnp: add ISAPnP MPU option quirks The AD181x and AZT230 chips don't support an IRQ-less MPU401 option but work fine without one. This adds (priority functional) IRQ-less options for each port option to help systems with few available IRQs. The AD1815 quirk can't use pnp_register_irq_resource() due to doubly penalizing the IRQ. Also, while not a practical issue due to no IRQ option being present for the dependents, this needs to add in front, not back. Doesn't use pnp_register_port_resource() for symetry with above. This does not delete the AD1815 independent option even though it should be empty after the IRQ transfer due to AD1816 coming with an empty but still present independent option by default. Was tested on AD1815, AD1816 and AZT2320. The ALSA snd-ad1818a driver also support the AZT2002 ID for MPU401 but this doesn't as I was unable to test it. Signed-off-by: Rene Herman Tested-by: Uwe Bugla Acked-by: Uwe Bugla Acked-by: Bjorn Helgaas Cc: Takashi Iwai Cc: Len Brown Signed-off-by: Linus Torvalds --- drivers/pnp/quirks.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index a1af2f9..ffdb12a 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -111,6 +111,113 @@ static void quirk_sb16audio_resources(struct pnp_dev *dev) dev_info(&dev->dev, "SB audio device quirk - increased port range\n"); } +static struct pnp_option *quirk_isapnp_mpu_options(struct pnp_dev *dev) +{ + struct pnp_option *head = NULL; + struct pnp_option *prev = NULL; + struct pnp_option *res; + + /* + * Build a functional IRQ-less variant of each MPU option. + */ + + for (res = dev->dependent; res; res = res->next) { + struct pnp_option *curr; + struct pnp_port *port; + struct pnp_port *copy; + + port = res->port; + if (!port || !res->irq) + continue; + + copy = pnp_alloc(sizeof *copy); + if (!copy) + break; + + copy->min = port->min; + copy->max = port->max; + copy->align = port->align; + copy->size = port->size; + copy->flags = port->flags; + + curr = pnp_build_option(PNP_RES_PRIORITY_FUNCTIONAL); + if (!curr) { + kfree(copy); + break; + } + curr->port = copy; + + if (prev) + prev->next = curr; + else + head = curr; + prev = curr; + } + if (head) + dev_info(&dev->dev, "adding IRQ-less MPU options\n"); + + return head; +} + +static void quirk_ad1815_mpu_resources(struct pnp_dev *dev) +{ + struct pnp_option *res; + struct pnp_irq *irq; + + /* + * Distribute the independent IRQ over the dependent options + */ + + res = dev->independent; + if (!res) + return; + + irq = res->irq; + if (!irq || irq->next) + return; + + res = dev->dependent; + if (!res) + return; + + while (1) { + struct pnp_irq *copy; + + copy = pnp_alloc(sizeof *copy); + if (!copy) + break; + + memcpy(copy->map, irq->map, sizeof copy->map); + copy->flags = irq->flags; + + copy->next = res->irq; /* Yes, this is NULL */ + res->irq = copy; + + if (!res->next) + break; + res = res->next; + } + kfree(irq); + + res->next = quirk_isapnp_mpu_options(dev); + + res = dev->independent; + res->irq = NULL; +} + +static void quirk_isapnp_mpu_resources(struct pnp_dev *dev) +{ + struct pnp_option *res; + + res = dev->dependent; + if (!res) + return; + + while (res->next) + res = res->next; + + res->next = quirk_isapnp_mpu_options(dev); +} #include @@ -205,6 +312,11 @@ static struct pnp_fixup pnp_fixups[] = { {"CTL0043", quirk_sb16audio_resources}, {"CTL0044", quirk_sb16audio_resources}, {"CTL0045", quirk_sb16audio_resources}, + /* Add IRQ-less MPU options */ + {"ADS7151", quirk_ad1815_mpu_resources}, + {"ADS7181", quirk_isapnp_mpu_resources}, + {"AZT0002", quirk_isapnp_mpu_resources}, + /* PnP resources that might overlap PCI BARs */ {"PNP0c01", quirk_system_pci_resources}, {"PNP0c02", quirk_system_pci_resources}, {""} -- cgit v1.1 From 3ef0f720e47e895b613b0305eb0a483e3ec11f23 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Wed, 14 May 2008 16:05:37 -0700 Subject: mm: fix infinite loop in filemap_fault filemap_fault will go into an infinite loop if ->readpage() fails asynchronously. AFAICS the bug was introduced by this commit, which removed the wait after the final readpage: commit d00806b183152af6d24f46f0c33f14162ca1262a Author: Nick Piggin Date: Thu Jul 19 01:46:57 2007 -0700 mm: fix fault vs invalidate race for linear mappings Fix by reintroducing the wait_on_page_locked() after ->readpage() to make sure the page is up-to-date before jumping back to the beginning of the function. I've noticed this while testing nfs exporting on fuse. The patch fixes it. Signed-off-by: Miklos Szeredi Cc: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/filemap.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/mm/filemap.c b/mm/filemap.c index 2dead9a..1e6a7d3 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -1461,6 +1461,11 @@ page_not_uptodate: */ ClearPageError(page); error = mapping->a_ops->readpage(file, page); + if (!error) { + wait_on_page_locked(page); + if (!PageUptodate(page)) + error = -EIO; + } page_cache_release(page); if (!error || error == AOP_TRUNCATED_PAGE) -- cgit v1.1 From 90898709dfca860d9550c85f0924007f4c0467ea Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Wed, 14 May 2008 16:05:38 -0700 Subject: atmel_lcdfb: fix initialization of a pre-allocated framebuffer Fix initialization of framebuffer not calling ioremap_writecombine() function and not using internal SRAM for at91sam9rl. This is a little rework of the "Don't initialize a pre-allocated framebuffer" patch that corrects the call to ioremap_writecombine() function. It also cuts the use of internal SRAM for at91sam9rl : it is a bit small for a framebuffer. Signed-off-by: Nicolas Ferre Cc: Andrew Victor Cc: Haavard Skinnemoen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-at91/at91sam9261_devices.c | 4 ++-- arch/arm/mach-at91/at91sam9rl_devices.c | 21 --------------------- 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index 728bb8f..0babb64 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -544,10 +544,10 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) struct resource *fb_res = &lcdc_resources[2]; size_t fb_len = fb_res->end - fb_res->start + 1; - fb = ioremap_writecombine(fb_res->start, fb_len); + fb = ioremap(fb_res->start, fb_len); if (fb) { memset(fb, 0, fb_len); - iounmap(fb, fb_len); + iounmap(fb); } } lcdc_data = *data; diff --git a/arch/arm/mach-at91/at91sam9rl_devices.c b/arch/arm/mach-at91/at91sam9rl_devices.c index 0546898..450db30 100644 --- a/arch/arm/mach-at91/at91sam9rl_devices.c +++ b/arch/arm/mach-at91/at91sam9rl_devices.c @@ -332,13 +332,6 @@ static struct resource lcdc_resources[] = { .end = AT91SAM9RL_ID_LCDC, .flags = IORESOURCE_IRQ, }, -#if defined(CONFIG_FB_INTSRAM) - [2] = { - .start = AT91SAM9RL_SRAM_BASE, - .end = AT91SAM9RL_SRAM_BASE + AT91SAM9RL_SRAM_SIZE - 1, - .flags = IORESOURCE_MEM, - }, -#endif }; static struct platform_device at91_lcdc_device = { @@ -381,20 +374,6 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_info *data) at91_set_B_periph(AT91_PIN_PC24, 0); /* LCDD22 */ at91_set_B_periph(AT91_PIN_PC25, 0); /* LCDD23 */ -#ifdef CONFIG_FB_INTSRAM - { - void __iomem *fb; - struct resource *fb_res = &lcdc_resources[2]; - size_t fb_len = fb_res->end - fb_res->start + 1; - - fb = ioremap_writecombine(fb_res->start, fb_len); - if (fb) { - memset(fb, 0, fb_len); - iounmap(fb, fb_len); - } - } -#endif - lcdc_data = *data; platform_device_register(&at91_lcdc_device); } -- cgit v1.1 From 3b7ec117bf6c98f5a845311c4ca5ca020a3d7689 Mon Sep 17 00:00:00 2001 From: Nate Case Date: Wed, 14 May 2008 16:05:39 -0700 Subject: ipmi: support I/O resources in OF driver The current OF probing assumes that the resource is IORESOURCE_MEM. This checks for the IORESOURCE_IO flag and behaves appropriately. An I/O resource can exist with an ipmi device node on a legacy ISA bus. Signed-off-by: Nate Case Signed-off-by: Corey Minyard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 5a54555..1926883 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2352,10 +2352,16 @@ static int __devinit ipmi_of_probe(struct of_device *dev, info->si_type = (enum si_type) match->data; info->addr_source = "device-tree"; - info->io_setup = mem_setup; info->irq_setup = std_irq_setup; - info->io.addr_type = IPMI_MEM_ADDR_SPACE; + if (resource.flags & IORESOURCE_IO) { + info->io_setup = port_setup; + info->io.addr_type = IPMI_IO_ADDR_SPACE; + } else { + info->io_setup = mem_setup; + info->io.addr_type = IPMI_MEM_ADDR_SPACE; + } + info->io.addr_data = resource.start; info->io.regsize = regsize ? *regsize : DEFAULT_REGSIZE; -- cgit v1.1 From c3723ca3874a8fc2218c4726d57e3a7da9e83e47 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 14 May 2008 16:05:40 -0700 Subject: memory hotplug: memmap_init_zone called twice __add_zone calls memmap_init_zone twice if memory gets attached to an empty zone. Once via init_currently_empty_zone and once explictly right after that call. Looks like this is currently not a bug, however the call is superfluous and might lead to subtle bugs if memmap_init_zone gets changed. So make sure it is called only once. Cc: Yasunori Goto Acked-by: KAMEZAWA Hiroyuki Cc: Dave Hansen Signed-off-by: Heiko Carstens Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory_hotplug.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index b17dca7..988bd91 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -167,13 +167,9 @@ static int __add_zone(struct zone *zone, unsigned long phys_start_pfn) int zone_type; zone_type = zone - pgdat->node_zones; - if (!zone->wait_table) { - int ret = 0; - ret = init_currently_empty_zone(zone, phys_start_pfn, - nr_pages, MEMMAP_HOTPLUG); - if (ret < 0) - return ret; - } + if (!zone->wait_table) + return init_currently_empty_zone(zone, phys_start_pfn, + nr_pages, MEMMAP_HOTPLUG); memmap_init_zone(nr_pages, nid, zone_type, phys_start_pfn, MEMMAP_HOTPLUG); return 0; -- cgit v1.1 From 772279c5f1dceb58d451dca94b557fd89b1ce890 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Wed, 14 May 2008 16:05:41 -0700 Subject: jbd: need to hold j_state_lock to updates to transaction t_state to T_COMMIT Updating the current transaction's t_state is protected by j_state_lock. We need to do the same when updating the t_state to T_COMMIT. Signed-off-by: Mingming Cao Acked-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/jbd/commit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index cd931ef..5a8ca61 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -470,7 +470,9 @@ void journal_commit_transaction(journal_t *journal) * transaction! Now comes the tricky part: we need to write out * metadata. Loop over the transaction's entire buffer list: */ + spin_lock(&journal->j_state_lock); commit_transaction->t_state = T_COMMIT; + spin_unlock(&journal->j_state_lock); J_ASSERT(commit_transaction->t_nr_buffers <= commit_transaction->t_outstanding_credits); -- cgit v1.1 From b7cffc1f29c1bc729bc50c863c87f93f9b70994b Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 14 May 2008 16:05:42 -0700 Subject: asm-{alpha,h8300,um,v850,xtensa}/param.h: unbreak HZ for userspace I noticed this because alpha was broken due to the recent commit commit bdc807871d58285737d50dc6163d0feb72cb0dc2 ("avoid overflows in kernel/time.c"). Most arches do something like this in their asm/param.h: #ifdef __KERNEL__ # define HZ CONFIG_HZ #else # define HZ 100 #endif A few arches though (namely alpha/h8300/um/v850/xtensa) either do no set HZ at all for !__KERNEL__, or they set it wrongly. This should bring all arches in line by setting up HZ for userspace. Without this currently perl 5.10 doesn't build on alpha: perl.c: In function 'perl_construct': perl.c:388: error: 'CONFIG_HZ' undeclared (first use in this function) -> http://buildd.debian.org/fetch.cgi?pkg=perl;ver=5.10.0-10;arch=alpha;stamp=1210252894 Signed-off-by: Mike Frysinger Cc: Richard Henderson Cc: Ivan Kokshaysky Cc: Yoshinori Sato Cc: Jeff Dike Cc: Chris Zankel Cc: maximilian attems Signed-off-by: Andrew Morton [ HZ on alpha is 1024 for historical reasons. - Linus ] Signed-off-by: Linus Torvalds --- include/asm-alpha/param.h | 4 ++++ include/asm-h8300/param.h | 8 +++----- include/asm-um/param.h | 2 ++ include/asm-v850/param.h | 2 ++ include/asm-xtensa/param.h | 2 ++ 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/include/asm-alpha/param.h b/include/asm-alpha/param.h index 0982f1d..e691ecf 100644 --- a/include/asm-alpha/param.h +++ b/include/asm-alpha/param.h @@ -5,8 +5,12 @@ hardware ignores reprogramming. We also need userland buy-in to the change in HZ, since this is visible in the wait4 resources etc. */ +#ifdef __KERNEL__ #define HZ CONFIG_HZ #define USER_HZ HZ +#else +#define HZ 1024 +#endif #define EXEC_PAGESIZE 8192 diff --git a/include/asm-h8300/param.h b/include/asm-h8300/param.h index 04f64f1..1c72fb8 100644 --- a/include/asm-h8300/param.h +++ b/include/asm-h8300/param.h @@ -1,14 +1,12 @@ #ifndef _H8300_PARAM_H #define _H8300_PARAM_H - -#ifndef HZ -#define HZ CONFIG_HZ -#endif - #ifdef __KERNEL__ +#define HZ CONFIG_HZ #define USER_HZ HZ #define CLOCKS_PER_SEC (USER_HZ) +#else +#define HZ 100 #endif #define EXEC_PAGESIZE 4096 diff --git a/include/asm-um/param.h b/include/asm-um/param.h index 4cd4a22..e44f4e6 100644 --- a/include/asm-um/param.h +++ b/include/asm-um/param.h @@ -13,6 +13,8 @@ #define HZ CONFIG_HZ #define USER_HZ 100 /* .. some user interfaces are in "ticks" */ #define CLOCKS_PER_SEC (USER_HZ) /* frequency at which times() counts */ +#else +#define HZ 100 #endif #endif diff --git a/include/asm-v850/param.h b/include/asm-v850/param.h index 2818326..4391f5f 100644 --- a/include/asm-v850/param.h +++ b/include/asm-v850/param.h @@ -26,6 +26,8 @@ # define HZ CONFIG_HZ # define USER_HZ 100 # define CLOCKS_PER_SEC USER_HZ +#else +# define HZ 100 #endif #endif /* __V850_PARAM_H__ */ diff --git a/include/asm-xtensa/param.h b/include/asm-xtensa/param.h index 82ad34d..ba03d5a 100644 --- a/include/asm-xtensa/param.h +++ b/include/asm-xtensa/param.h @@ -15,6 +15,8 @@ # define HZ CONFIG_HZ /* internal timer frequency */ # define USER_HZ 100 /* for user interfaces in "ticks" */ # define CLOCKS_PER_SEC (USER_HZ) /* frequnzy at which times() counts */ +#else +# define HZ 100 #endif #define EXEC_PAGESIZE 4096 -- cgit v1.1 From 0c70814c311581a6c86198db4f982aa683c68fb8 Mon Sep 17 00:00:00 2001 From: Mirco Tischler Date: Wed, 14 May 2008 16:05:46 -0700 Subject: cgroups: fix compile warning Return type of cpu_rt_runtime_write() should be int instead of ssize_t. Signed-off-by: Mirco Tischler Acked-by: Paul Menage Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/sched.c b/kernel/sched.c index 8841a91..cfa222a 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -8986,7 +8986,7 @@ static u64 cpu_shares_read_u64(struct cgroup *cgrp, struct cftype *cft) #endif #ifdef CONFIG_RT_GROUP_SCHED -static ssize_t cpu_rt_runtime_write(struct cgroup *cgrp, struct cftype *cft, +static int cpu_rt_runtime_write(struct cgroup *cgrp, struct cftype *cft, s64 val) { return sched_group_set_rt_runtime(cgroup_tg(cgrp), val); -- cgit v1.1 From 7e01c8e5420b6c7f9d85d34c15d8c7a15c9fc720 Mon Sep 17 00:00:00 2001 From: Tiger Yang Date: Wed, 14 May 2008 16:05:47 -0700 Subject: ext3/4: fix uninitialized bs in ext3/4_xattr_set_handle() This fix the uninitialized bs when we try to replace a xattr entry in ibody with the new value which require more than free space. This situation only happens we format ext3/4 with inode size more than 128 and we have put xattr entries both in ibody and block. The consequences about this bug is we will lost the xattr block which pointed by i_file_acl with all xattr entires in it. We will alloc a new xattr block and put that large value entry in it. The old xattr block will become orphan block. Signed-off-by: Tiger Yang Cc: Cc: Andreas Gruenbacher Acked-by: Andreas Dilger Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ext3/xattr.c | 5 +++++ fs/ext4/xattr.c | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index d4a4f0e..175414a 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -1000,6 +1000,11 @@ ext3_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, i.value = NULL; error = ext3_xattr_block_set(handle, inode, &i, &bs); } else if (error == -ENOSPC) { + if (EXT3_I(inode)->i_file_acl && !bs.s.base) { + error = ext3_xattr_block_find(inode, &i, &bs); + if (error) + goto cleanup; + } error = ext3_xattr_block_set(handle, inode, &i, &bs); if (error) goto cleanup; diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c index 3fbc2c6..ff08633 100644 --- a/fs/ext4/xattr.c +++ b/fs/ext4/xattr.c @@ -1009,6 +1009,11 @@ ext4_xattr_set_handle(handle_t *handle, struct inode *inode, int name_index, i.value = NULL; error = ext4_xattr_block_set(handle, inode, &i, &bs); } else if (error == -ENOSPC) { + if (EXT4_I(inode)->i_file_acl && !bs.s.base) { + error = ext4_xattr_block_find(inode, &i, &bs); + if (error) + goto cleanup; + } error = ext4_xattr_block_set(handle, inode, &i, &bs); if (error) goto cleanup; -- cgit v1.1 From 122a881c776b7c155bf3f379928cc27aab435288 Mon Sep 17 00:00:00 2001 From: Robin Getz Date: Wed, 14 May 2008 16:05:48 -0700 Subject: video/logo: add support for Blackfin/Linux logo for framebuffer console This art design is beautiful, isn't it? And you can watch our demo on YouTube: http://youtube.com/watch?v=fKyQOntPEFs Signed-off-by: Robin Getz Signed-off-by: Bryan Wu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/logo/Kconfig | 10 + drivers/video/logo/Makefile | 2 + drivers/video/logo/logo.c | 10 + drivers/video/logo/logo_blackfin_clut224.ppm | 1127 ++++++++++++++++++++++++++ drivers/video/logo/logo_blackfin_vga16.ppm | 1127 ++++++++++++++++++++++++++ 5 files changed, 2276 insertions(+) create mode 100644 drivers/video/logo/logo_blackfin_clut224.ppm create mode 100644 drivers/video/logo/logo_blackfin_vga16.ppm diff --git a/drivers/video/logo/Kconfig b/drivers/video/logo/Kconfig index 9de1c11..39ac49e 100644 --- a/drivers/video/logo/Kconfig +++ b/drivers/video/logo/Kconfig @@ -27,6 +27,16 @@ config LOGO_LINUX_CLUT224 bool "Standard 224-color Linux logo" default y +config LOGO_BLACKFIN_VGA16 + bool "16-colour Blackfin Processor Linux logo" + depends on BLACKFIN + default y + +config LOGO_BLACKFIN_CLUT224 + bool "224-colour Blackfin Processor Linux logo" + depends on BLACKFIN + default y + config LOGO_DEC_CLUT224 bool "224-color Digital Equipment Corporation Linux logo" depends on MACH_DECSTATION || ALPHA diff --git a/drivers/video/logo/Makefile b/drivers/video/logo/Makefile index a5fc4ed..b91251d 100644 --- a/drivers/video/logo/Makefile +++ b/drivers/video/logo/Makefile @@ -4,6 +4,8 @@ obj-$(CONFIG_LOGO) += logo.o obj-$(CONFIG_LOGO_LINUX_MONO) += logo_linux_mono.o obj-$(CONFIG_LOGO_LINUX_VGA16) += logo_linux_vga16.o obj-$(CONFIG_LOGO_LINUX_CLUT224) += logo_linux_clut224.o +obj-$(CONFIG_LOGO_BLACKFIN_CLUT224) += logo_blackfin_clut224.o +obj-$(CONFIG_LOGO_BLACKFIN_VGA16) += logo_blackfin_vga16.o obj-$(CONFIG_LOGO_DEC_CLUT224) += logo_dec_clut224.o obj-$(CONFIG_LOGO_MAC_CLUT224) += logo_mac_clut224.o obj-$(CONFIG_LOGO_PARISC_CLUT224) += logo_parisc_clut224.o diff --git a/drivers/video/logo/logo.c b/drivers/video/logo/logo.c index fc72684..2e85a2b 100644 --- a/drivers/video/logo/logo.c +++ b/drivers/video/logo/logo.c @@ -24,6 +24,8 @@ extern const struct linux_logo logo_linux_mono; extern const struct linux_logo logo_linux_vga16; extern const struct linux_logo logo_linux_clut224; +extern const struct linux_logo logo_blackfin_vga16; +extern const struct linux_logo logo_blackfin_clut224; extern const struct linux_logo logo_dec_clut224; extern const struct linux_logo logo_mac_clut224; extern const struct linux_logo logo_parisc_clut224; @@ -65,6 +67,10 @@ const struct linux_logo * __init_refok fb_find_logo(int depth) /* Generic Linux logo */ logo = &logo_linux_vga16; #endif +#ifdef CONFIG_LOGO_BLACKFIN_VGA16 + /* Blackfin processor logo */ + logo = &logo_blackfin_vga16; +#endif #ifdef CONFIG_LOGO_SUPERH_VGA16 /* SuperH Linux logo */ logo = &logo_superh_vga16; @@ -76,6 +82,10 @@ const struct linux_logo * __init_refok fb_find_logo(int depth) /* Generic Linux logo */ logo = &logo_linux_clut224; #endif +#ifdef CONFIG_LOGO_BLACKFIN_CLUT224 + /* Blackfin Linux logo */ + logo = &logo_blackfin_clut224; +#endif #ifdef CONFIG_LOGO_DEC_CLUT224 /* DEC Linux logo on MIPS/MIPS64 or ALPHA */ logo = &logo_dec_clut224; diff --git a/drivers/video/logo/logo_blackfin_clut224.ppm b/drivers/video/logo/logo_blackfin_clut224.ppm new file mode 100644 index 0000000..dc9a50a --- /dev/null +++ b/drivers/video/logo/logo_blackfin_clut224.ppm @@ -0,0 +1,1127 @@ +P3 +# This was generated by the GIMP & Netpbm tools +# gimp linux_bf.svg (create 80x80 save as linux_bf.ppm) +# pnmquant 224 linux_bf.ppm | pnmnoraw > logo_blackfin_clut224.ppm +# +80 80 +255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 3 3 3 4 6 6 6 6 6 4 6 6 3 3 3 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 2 2 2 10 10 10 26 26 27 +44 44 45 66 66 66 78 81 81 78 81 81 75 75 76 60 60 60 +39 39 39 20 20 20 6 6 6 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 2 2 2 14 14 14 47 47 47 84 84 84 75 75 76 +47 47 47 12 12 12 0 0 0 0 0 0 0 0 0 20 20 20 +53 54 54 81 81 82 74 74 74 31 31 31 6 6 6 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4 4 4 34 34 35 84 84 84 60 60 60 4 4 4 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 17 18 18 75 75 76 66 66 66 17 18 18 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 +42 42 43 84 84 84 8 8 8 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 3 3 36 40 40 10 16 16 0 0 0 31 31 31 84 84 84 +29 29 30 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 26 27 27 +84 84 84 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +15 19 19 114 115 115 110 114 114 44 46 46 0 0 0 12 12 12 +90 87 86 24 24 24 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 8 8 8 75 75 76 +14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +30 40 40 133 133 133 129 130 130 78 85 85 23 31 30 0 0 0 +19 19 19 78 81 81 13 13 13 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 26 27 27 81 81 82 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +36 40 40 89 90 91 55 63 63 23 31 30 4 6 6 0 0 0 +0 0 0 60 60 60 47 47 47 2 2 2 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 2 2 2 53 54 54 34 34 35 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4 10 10 7 9 9 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 84 84 84 13 13 13 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 4 6 6 78 81 81 2 2 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 65 64 64 36 36 36 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 10 11 11 81 81 82 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 12 12 12 67 70 70 4 4 4 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 16 16 16 81 81 82 0 0 0 +0 0 0 0 0 0 4 10 10 44 50 50 18 21 21 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 1 1 78 85 85 120 121 122 7 9 9 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 82 82 81 12 12 12 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 19 19 19 81 81 82 0 0 0 +0 0 0 2 2 2 8 8 8 55 63 63 108 110 110 52 58 58 +0 0 0 0 0 0 0 0 0 0 0 0 42 42 43 129 130 130 +140 142 143 114 115 115 110 114 114 129 130 130 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 75 75 76 24 24 24 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 19 19 19 74 74 74 0 0 0 +4 6 6 167 168 167 196 196 197 196 196 197 61 65 66 78 85 85 +0 0 0 0 0 0 0 0 0 118 118 118 202 202 203 219 219 219 +219 219 219 214 214 215 187 187 188 78 85 85 29 33 34 0 0 0 +0 0 0 0 0 0 0 0 0 60 60 60 39 39 39 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 19 19 19 72 71 71 0 0 0 +185 185 184 244 245 245 250 251 252 251 251 252 247 248 249 36 36 36 +0 0 0 0 0 0 13 13 13 243 243 241 252 252 252 253 253 253 +253 253 253 252 252 252 247 247 246 193 193 194 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 42 42 43 50 51 51 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 19 19 19 78 81 81 0 0 0 +247 247 246 193 193 194 95 97 97 193 193 194 255 255 255 237 237 238 +0 0 0 0 0 0 202 202 203 255 255 255 247 247 246 108 107 107 +82 85 86 167 168 167 255 255 255 248 248 249 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 34 34 35 56 56 56 2 2 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 19 19 19 78 81 81 0 0 0 +250 250 251 50 51 51 153 154 155 150 151 151 244 245 245 244 245 245 +44 50 50 84 89 89 153 154 155 255 255 255 140 142 143 0 0 0 +149 149 150 156 155 156 237 237 238 254 254 254 67 70 70 0 0 0 +0 0 0 0 0 0 0 0 0 39 39 39 47 47 47 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 19 19 19 81 81 82 0 0 0 +248 248 249 34 34 35 72 71 71 165 165 165 202 202 203 244 245 245 +10 16 16 82 85 86 89 90 91 255 255 255 95 97 97 0 0 0 +0 0 0 53 54 54 177 177 174 255 255 255 127 127 126 0 0 0 +0 0 0 0 0 0 0 0 0 39 39 39 36 36 36 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 14 14 14 78 81 81 0 0 0 +243 243 243 89 90 91 0 0 0 36 40 40 201 147 55 241 205 27 +241 205 27 241 205 27 241 205 27 238 192 33 108 110 110 0 0 0 +0 0 0 0 0 0 191 190 190 254 254 254 34 34 35 0 0 0 +0 0 0 0 0 0 0 0 0 42 42 43 42 42 43 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 10 10 10 75 75 76 0 0 0 +202 202 203 218 217 217 21 19 17 230 165 41 199 129 48 213 157 40 +244 212 23 243 206 27 180 121 62 243 206 27 244 209 25 226 179 40 +15 10 7 103 103 103 254 254 254 251 251 252 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 17 18 18 58 58 58 2 2 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 9 9 9 84 84 84 0 0 0 +0 0 0 226 226 219 213 157 40 244 209 25 245 211 23 245 211 23 +245 214 38 245 214 38 245 211 23 245 211 23 245 211 23 244 212 23 +244 212 23 241 205 27 226 179 40 196 196 197 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 74 74 74 4 6 6 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 7 7 84 84 84 0 0 0 +54 42 32 213 157 40 243 206 27 245 211 23 245 211 23 245 211 23 +245 215 41 245 214 35 245 211 23 245 211 23 245 214 35 245 215 41 +245 214 35 245 211 23 245 211 23 238 204 29 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 81 81 82 12 12 12 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 4 6 6 74 74 74 0 0 0 +201 147 55 241 205 27 245 211 23 245 211 23 245 211 23 245 213 29 +245 214 38 245 211 23 245 211 23 245 214 35 245 215 41 245 215 41 +245 213 29 142 83 36 142 83 36 244 209 25 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 74 74 74 25 25 26 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 4 4 4 72 71 71 6 6 6 +213 157 40 244 209 25 245 211 23 245 211 23 245 211 23 245 213 29 +244 212 23 245 211 23 245 214 35 245 215 41 245 215 41 245 213 29 +142 83 36 142 83 36 238 192 33 241 205 27 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 44 44 44 49 50 50 +2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 3 3 3 65 64 64 17 18 18 +199 129 48 199 129 48 245 211 23 245 211 23 245 211 23 245 211 23 +245 211 23 244 212 23 245 214 38 245 214 38 142 83 36 142 83 36 +142 83 36 245 211 23 244 210 23 230 165 41 0 0 0 0 0 0 +78 81 81 114 115 115 73 79 79 0 0 0 3 3 3 81 81 82 +9 9 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 49 50 50 29 29 30 +90 87 86 199 129 48 173 101 51 173 101 51 245 211 23 245 211 23 +245 211 23 230 165 41 142 83 36 142 83 36 142 83 36 245 211 23 +244 210 23 241 205 27 230 165 41 175 173 165 3 3 3 0 0 0 +44 46 46 118 118 118 118 118 118 108 110 110 0 0 0 75 75 76 +28 28 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 52 53 53 26 26 27 +118 118 118 175 173 165 199 129 48 173 101 51 173 101 51 173 101 51 +173 101 51 142 83 36 173 101 51 245 211 23 244 209 25 238 204 29 +213 157 40 214 196 166 227 227 227 214 214 215 120 121 122 0 0 0 +0 0 0 108 110 110 118 118 118 118 118 118 0 0 0 23 23 23 +66 66 66 4 6 6 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 7 7 75 75 76 4 4 4 +127 127 126 205 205 205 181 181 181 199 129 48 226 179 40 244 209 25 +244 209 25 244 209 25 243 206 27 238 192 33 213 157 40 187 166 103 +234 234 234 248 248 249 251 252 252 248 248 249 214 214 215 0 0 0 +0 0 0 0 0 0 103 103 103 100 103 103 0 0 0 0 0 0 +78 81 81 24 24 24 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 26 27 27 82 82 81 0 0 0 +146 146 147 234 234 234 222 221 221 178 178 179 180 121 62 213 157 40 +213 157 40 213 157 40 201 147 55 180 121 62 219 219 219 243 243 241 +253 253 253 255 255 255 255 255 255 255 255 255 250 250 251 120 121 122 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +20 20 20 72 71 71 8 8 8 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 10 10 10 75 75 76 22 22 22 0 0 0 +205 205 205 253 253 253 247 248 249 212 211 212 178 178 179 161 161 162 +165 165 165 181 181 181 205 205 205 227 227 227 244 245 245 254 254 254 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 239 239 240 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 67 70 70 39 39 39 2 2 2 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 4 4 4 50 51 51 60 60 60 0 0 0 16 16 16 +249 250 251 255 255 255 255 255 255 240 240 240 209 210 210 193 193 194 +200 200 197 212 211 212 231 231 231 246 247 248 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 253 253 253 +153 154 155 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 3 3 3 84 84 84 20 20 20 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2 2 2 33 33 34 81 81 82 0 0 0 0 0 0 231 231 231 +255 255 255 255 255 255 255 255 255 253 253 253 234 234 234 222 221 221 +227 227 227 237 237 238 250 250 251 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +240 240 240 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 26 27 27 72 71 71 8 8 8 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +21 21 22 84 84 84 7 7 7 0 0 0 150 151 151 252 252 252 +255 255 255 255 255 255 255 255 255 255 255 255 252 252 252 244 245 245 +246 247 248 253 253 253 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +251 251 252 9 9 9 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 65 64 64 47 47 47 3 3 3 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 12 12 +75 75 76 26 26 27 0 0 0 1 1 1 239 239 240 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 202 202 203 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 84 84 84 28 28 29 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 4 4 4 55 55 55 +60 60 60 0 0 0 0 0 0 95 97 97 248 248 249 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 244 245 245 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 14 14 14 82 82 81 +15 15 15 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 29 29 30 84 84 84 +0 0 0 0 0 0 0 0 0 156 155 156 247 247 246 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 247 247 246 240 240 240 232 232 233 232 232 233 +243 243 243 253 253 253 53 54 54 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 44 44 44 +60 60 60 6 6 6 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 10 10 10 81 81 82 14 14 14 +0 0 0 0 0 0 6 6 6 150 151 151 214 214 215 250 251 252 +255 255 255 255 255 255 255 255 255 246 247 248 218 217 217 214 214 215 +218 217 217 244 245 245 255 255 255 255 255 255 255 255 255 250 248 249 +232 232 233 214 214 215 196 196 197 182 183 184 181 181 181 181 181 181 +187 187 188 240 240 240 232 232 233 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +78 81 81 34 34 35 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 39 39 39 74 74 74 0 0 0 +0 0 0 0 0 0 60 60 60 161 161 162 200 200 197 229 229 230 +251 251 252 255 255 255 255 255 255 255 255 255 243 243 241 214 214 215 +248 248 249 255 255 255 255 255 255 255 255 255 255 255 255 254 254 254 +239 239 240 214 214 215 193 193 194 182 183 184 178 178 179 176 177 177 +176 177 177 182 183 184 248 248 249 14 14 14 0 0 0 61 65 66 +10 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +10 10 10 84 84 84 13 13 13 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 10 11 11 82 82 81 7 7 7 0 0 0 +0 0 0 0 0 0 165 165 165 229 229 230 249 250 251 254 254 254 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 253 253 253 240 240 240 227 227 227 205 205 205 +181 181 181 176 177 177 191 190 190 227 227 227 0 0 0 44 50 50 +84 89 89 61 65 66 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 58 58 58 49 50 50 3 3 3 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 36 36 36 66 66 66 0 0 0 29 33 34 +0 3 3 26 27 27 234 234 234 254 254 254 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +254 254 254 253 253 254 252 253 253 253 253 254 253 254 254 253 254 254 +254 254 254 255 255 255 255 255 255 255 255 255 255 255 255 251 251 252 +227 227 227 187 187 188 176 177 177 222 221 221 13 13 13 0 0 0 +12 15 14 73 79 79 36 40 40 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 90 87 86 17 18 18 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 7 7 7 78 81 81 12 12 12 23 31 30 52 58 58 +0 0 0 209 210 210 253 253 253 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 254 254 254 +251 251 252 150 151 151 103 103 103 129 130 130 196 196 197 250 250 251 +252 252 253 254 254 254 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 240 240 240 193 193 194 196 196 197 229 229 230 0 0 0 +0 0 0 4 10 10 30 40 40 0 3 3 0 0 0 0 0 0 +0 0 0 0 0 0 47 47 47 53 54 54 3 3 3 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 23 23 23 81 81 82 0 0 0 52 58 58 36 40 40 +42 42 43 250 250 251 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 254 254 254 +227 227 227 7 7 7 7 7 7 7 7 7 7 7 7 44 44 45 +156 155 156 249 250 251 253 253 253 254 254 254 255 255 255 255 255 255 +255 255 255 255 255 255 247 247 246 222 221 221 239 239 240 0 0 0 +30 40 40 44 50 50 23 31 30 29 33 34 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 90 87 86 16 16 16 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2 2 2 50 51 51 42 42 43 29 33 34 52 58 58 0 0 0 +232 232 233 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 254 254 254 +250 251 252 44 44 44 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 56 56 56 209 210 210 252 252 253 254 254 254 255 255 255 +255 255 255 255 255 255 255 255 255 254 253 253 249 250 251 146 146 147 +36 40 40 44 50 50 36 40 40 67 70 70 61 65 66 0 0 0 +0 0 0 0 0 0 0 0 0 55 55 55 44 44 45 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +10 10 10 81 81 82 1 1 1 52 58 58 44 50 50 52 53 53 +251 251 252 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 254 254 254 +253 253 253 187 187 188 8 8 8 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 19 19 19 178 178 179 252 252 253 254 254 254 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 237 237 238 +10 16 16 30 40 40 0 3 3 23 31 30 84 89 89 0 0 0 +0 0 0 0 0 0 0 0 0 3 3 3 81 81 82 9 9 9 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +29 29 30 72 71 71 10 16 16 52 58 58 0 0 0 222 221 221 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +254 254 254 251 251 252 95 97 97 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 10 10 10 161 161 162 251 252 252 +254 254 254 255 255 255 255 255 255 255 255 255 255 255 255 248 248 249 +0 0 0 0 0 0 0 0 0 0 0 0 84 89 89 0 3 3 +0 0 0 0 0 0 0 0 0 0 0 0 74 74 74 26 27 27 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 4 4 4 +65 64 64 20 20 20 20 25 25 30 40 40 0 0 0 247 247 246 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 253 253 254 222 221 221 9 9 9 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 8 8 8 149 149 150 +252 252 253 254 254 254 255 255 255 255 255 255 255 255 255 252 252 252 +0 0 0 0 0 0 0 0 0 0 0 0 73 79 79 12 15 14 +0 0 0 0 0 0 0 0 0 0 0 0 36 36 36 58 58 58 +3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 20 20 20 +74 74 74 0 0 0 4 10 10 4 10 10 36 36 36 252 252 252 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 227 227 227 253 253 253 255 255 255 +255 255 255 254 254 254 250 251 252 65 64 64 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 8 8 8 +146 146 147 251 252 252 254 254 254 255 255 255 255 255 255 253 254 254 +0 0 0 0 0 0 0 0 0 0 0 0 52 58 58 10 16 16 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 82 82 81 +9 9 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 4 6 6 65 64 64 +25 25 25 0 3 3 30 40 40 0 0 0 187 187 188 254 254 254 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 193 193 194 253 252 252 255 255 255 +255 255 255 255 255 255 252 253 253 129 130 130 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +8 8 8 149 149 150 252 252 253 254 254 254 255 255 255 254 254 254 +52 53 53 0 0 0 0 0 0 0 0 0 20 25 25 2 5 4 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 81 81 82 +20 20 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 26 26 27 81 81 82 +0 0 0 18 21 21 73 79 79 0 0 0 237 237 238 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 182 183 184 255 255 255 255 255 255 +255 255 255 255 255 255 253 253 253 176 177 177 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 8 8 8 153 154 155 251 252 252 254 254 254 255 255 255 +150 151 151 0 0 0 0 0 0 0 0 0 20 25 25 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 65 64 64 +33 33 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 6 6 6 67 70 70 20 20 20 +0 0 0 23 31 30 82 85 86 0 0 0 247 247 246 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 182 183 184 255 255 255 255 255 255 +255 255 255 255 255 255 253 254 254 214 214 215 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 8 8 8 156 155 156 252 252 253 254 254 254 +167 168 167 0 0 0 0 0 0 0 0 0 67 70 70 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 47 47 47 +44 44 44 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 21 21 22 75 75 76 0 0 0 +0 0 0 29 33 34 84 89 89 0 0 0 248 248 249 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 248 248 249 181 181 181 255 255 255 255 255 255 +255 255 255 255 255 255 254 254 254 240 240 240 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 8 8 8 161 161 162 251 252 252 +185 185 184 4 4 4 0 0 0 10 11 11 100 103 103 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 36 36 36 +55 55 55 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 33 33 34 50 51 51 0 0 0 +0 0 0 9 11 11 82 85 86 10 16 16 248 248 249 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 245 244 245 179 180 181 255 255 255 255 255 255 +255 255 255 255 255 255 254 254 254 251 252 252 20 20 20 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 10 10 10 161 161 162 +205 205 205 17 18 18 0 0 0 95 97 97 78 81 81 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 36 36 36 +53 54 54 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 31 31 31 58 58 58 0 0 0 +0 0 0 0 0 0 67 70 70 78 81 81 248 248 249 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 234 234 234 179 180 181 255 255 255 255 255 255 +255 255 255 255 255 255 254 254 254 251 252 252 23 23 23 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +10 11 11 84 84 84 161 161 162 209 210 210 229 229 230 237 237 238 +202 202 203 26 26 27 9 11 11 44 50 50 0 0 0 4 6 6 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 52 53 53 +39 39 39 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 23 23 23 78 81 81 213 157 40 +243 206 27 243 206 27 54 42 32 73 79 79 222 221 221 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 238 238 236 178 178 179 255 255 255 255 255 255 +255 255 255 255 255 255 254 254 254 251 252 253 36 36 36 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 84 84 84 +222 221 221 251 252 252 252 253 253 253 253 253 253 254 254 252 252 253 +146 146 147 140 142 143 156 155 156 110 114 114 26 27 27 82 85 86 +84 89 89 95 97 97 36 40 40 0 0 0 0 0 0 74 74 74 +23 23 23 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 14 14 14 +24 24 24 26 26 27 26 26 27 26 26 27 25 25 26 21 21 22 +7 7 7 0 0 0 1 1 1 34 34 35 238 192 33 244 210 23 +244 212 23 244 212 23 244 210 23 88 79 47 200 200 197 254 254 254 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 244 245 245 179 180 181 255 255 255 255 255 255 +255 255 255 255 255 255 254 254 254 252 252 253 36 36 36 7 7 7 +7 7 7 7 7 7 7 7 7 8 8 8 149 149 150 251 251 252 +252 252 253 253 253 253 253 253 253 250 248 249 239 223 156 239 223 156 +120 121 122 182 183 184 176 177 177 120 121 122 33 33 34 3 3 3 +0 0 0 67 70 70 146 146 147 20 25 25 1 1 1 82 82 81 +9 9 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 19 19 19 89 90 91 +146 146 147 150 151 151 150 151 151 150 151 151 150 151 151 129 130 130 +58 58 58 6 6 6 14 14 14 201 147 55 245 211 23 245 213 29 +245 214 35 245 215 41 245 213 29 244 210 23 142 83 36 232 232 233 +254 254 254 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 185 185 184 255 255 255 255 255 255 +255 255 255 255 255 255 254 254 254 251 252 252 50 51 51 7 7 7 +7 7 7 7 7 7 7 7 7 146 146 147 251 252 252 252 253 253 +251 252 253 239 239 240 171 168 154 129 130 130 137 136 134 175 173 165 +221 218 200 65 64 64 22 22 22 186 186 187 114 115 115 26 26 27 +2 2 2 0 0 0 61 65 66 31 33 27 238 192 33 108 96 91 +9 9 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 2 2 2 52 53 53 178 178 179 +21 21 22 7 7 7 7 7 7 7 7 7 7 7 7 118 118 118 +137 136 134 36 36 36 65 64 64 243 206 27 244 212 23 245 215 41 +245 215 41 245 215 41 245 215 41 244 209 25 244 209 25 1 1 1 +219 219 219 253 253 253 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 214 214 215 255 255 255 255 255 255 +255 255 255 255 255 255 254 254 254 252 252 253 50 51 51 7 7 7 +7 7 7 7 7 7 84 84 84 250 251 252 252 253 253 251 251 252 +167 168 167 22 22 22 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 34 34 35 187 187 188 103 103 103 +29 29 30 3 3 3 7 9 9 238 204 29 245 215 41 245 214 35 +28 28 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 7 7 90 87 86 178 178 179 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 16 16 16 +193 193 194 133 133 133 187 166 103 245 218 76 245 218 76 245 216 51 +245 216 51 245 218 76 246 224 96 245 218 76 245 218 76 245 218 76 +25 25 25 186 186 187 252 252 252 254 254 254 254 254 254 253 254 254 +254 254 254 254 254 254 254 254 254 246 247 248 254 254 254 253 254 254 +254 254 254 254 254 254 253 254 254 251 252 252 36 36 36 7 7 7 +7 7 7 20 20 20 229 229 230 253 253 253 252 253 253 178 178 179 +10 10 10 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 42 42 43 196 196 197 +118 118 118 33 33 34 238 204 29 245 215 41 245 215 41 245 215 41 +49 50 50 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 17 18 18 120 121 122 137 136 134 +7 7 7 7 7 7 34 34 35 20 20 20 7 7 7 7 7 7 +202 202 203 209 206 202 193 187 162 193 187 162 248 234 156 245 218 76 +245 218 76 248 234 156 193 187 162 193 187 162 193 187 162 214 196 166 +240 219 129 95 97 97 196 196 197 186 186 187 187 187 188 196 196 197 +252 252 253 251 252 253 212 211 212 187 187 188 196 196 197 251 252 252 +218 217 217 187 187 188 191 190 190 250 251 252 24 24 24 7 7 7 +7 7 7 110 114 114 252 252 253 253 254 254 250 251 252 89 90 91 +89 90 91 129 130 130 127 127 126 44 44 44 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 49 50 50 +202 202 203 214 196 166 245 216 51 245 214 38 245 214 35 245 214 38 +58 58 58 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 31 31 31 156 155 156 82 82 81 +7 7 7 10 10 10 237 237 238 66 66 66 7 7 7 25 25 25 +247 248 249 81 81 82 7 7 7 31 31 31 247 237 174 245 218 76 +246 226 108 200 200 197 7 7 7 7 7 7 7 7 7 137 136 134 +247 237 174 193 193 194 72 71 71 7 7 7 7 7 7 8 8 8 +196 196 197 250 251 252 67 70 70 7 7 7 84 84 84 244 245 245 +47 47 47 7 7 7 118 118 118 249 250 251 12 12 12 7 7 7 +9 9 9 218 217 217 253 253 253 254 254 254 252 253 253 251 251 252 +249 250 251 237 237 238 95 97 97 9 9 9 15 15 15 95 97 97 +47 47 47 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +66 66 66 240 230 197 246 226 108 245 214 38 245 211 23 244 212 23 +65 64 64 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 2 2 2 52 53 53 185 185 184 25 25 25 +7 7 7 60 60 60 240 240 240 14 14 14 7 7 7 84 84 84 +247 248 249 23 23 23 7 7 7 94 91 88 248 234 156 245 218 76 +248 234 156 127 127 126 7 7 7 7 7 7 7 7 7 167 168 167 +251 248 240 65 64 64 7 7 7 7 7 7 7 7 7 7 7 7 +84 84 84 243 243 243 15 15 15 7 7 7 140 142 143 146 146 147 +7 7 7 33 33 34 237 237 238 243 243 243 21 21 22 120 121 122 +218 217 217 252 252 253 254 254 254 253 253 254 252 253 253 251 252 252 +247 248 249 72 71 71 7 7 7 58 58 58 222 221 221 248 248 249 +75 75 76 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 82 82 81 246 239 193 246 226 108 245 216 51 245 214 38 +238 192 33 21 21 22 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 8 8 8 90 87 86 182 183 184 7 7 7 +7 7 7 120 121 122 187 187 188 7 7 7 7 7 7 146 146 147 +205 205 205 7 7 7 7 7 7 153 153 148 240 219 129 246 224 96 +246 239 193 39 39 39 60 60 60 108 110 110 7 7 7 202 202 203 +227 227 227 7 7 7 7 7 7 205 205 205 89 90 91 7 7 7 +120 121 122 193 193 194 7 7 7 7 7 7 186 186 187 25 25 25 +7 7 7 167 168 167 251 251 252 243 243 243 214 214 215 250 251 252 +251 252 253 254 254 254 253 253 253 219 219 219 140 140 139 140 140 139 +118 118 118 7 7 7 52 53 53 237 237 238 247 247 246 176 177 177 +8 8 8 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 95 97 97 246 239 193 246 226 108 245 216 51 +245 214 38 201 147 55 31 31 31 103 103 103 103 103 103 72 71 71 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 17 18 18 127 127 126 140 140 139 7 7 7 +7 7 7 17 18 18 17 18 18 7 7 7 95 97 97 244 245 245 +146 146 147 7 7 7 7 7 7 200 200 197 246 226 108 240 219 129 +194 194 184 7 7 7 140 140 139 89 90 91 7 7 7 232 232 233 +165 165 165 7 7 7 31 31 31 249 250 251 39 39 39 7 7 7 +176 177 177 133 133 133 7 7 7 22 22 22 108 110 110 7 7 7 +72 71 71 251 252 252 252 253 253 250 251 252 247 248 249 205 205 205 +251 252 253 254 254 254 252 252 253 84 84 84 7 7 7 7 7 7 +7 7 7 7 7 7 140 142 143 247 248 249 140 140 139 14 14 14 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 16 16 16 +14 14 14 7 7 7 7 7 7 114 115 115 246 239 193 246 224 96 +245 216 51 245 216 51 243 235 220 176 177 177 185 185 184 229 229 230 +47 47 47 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 31 31 31 156 155 156 90 87 86 7 7 7 +7 7 7 7 7 7 7 7 7 31 31 31 243 243 241 247 247 246 +84 84 84 7 7 7 26 27 27 246 239 193 246 226 108 248 234 156 +108 110 110 7 7 7 212 211 212 44 44 44 22 22 22 249 250 251 +108 107 107 7 7 7 89 90 91 238 238 236 114 115 115 118 118 118 +231 231 231 75 75 76 7 7 7 34 34 35 10 11 11 12 12 12 +214 214 215 253 253 253 253 253 253 200 200 197 31 31 31 103 103 103 +252 252 253 252 253 253 218 217 217 9 9 9 7 7 7 7 7 7 +7 7 7 7 7 7 25 25 25 39 39 39 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 103 103 103 234 234 234 +181 181 181 7 7 7 7 7 7 7 7 7 133 133 133 247 237 174 +246 224 96 246 226 108 185 185 184 177 177 174 153 154 155 181 181 181 +140 140 139 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 1 1 1 49 50 50 186 186 187 28 28 28 7 7 7 +12 12 12 22 22 22 7 7 7 7 7 7 108 107 107 247 247 246 +25 25 25 7 7 7 90 87 86 247 237 174 246 226 108 246 239 193 +28 28 28 44 44 44 237 237 238 9 9 9 53 54 54 249 250 251 +49 50 50 7 7 7 153 153 148 249 241 199 214 196 166 185 185 184 +229 229 230 19 19 19 7 7 7 7 7 7 7 7 7 103 103 103 +251 252 253 254 254 254 253 253 253 150 151 151 7 7 7 187 187 188 +252 252 253 251 251 252 103 103 103 7 7 7 7 7 7 7 7 7 +7 7 7 23 23 23 17 18 18 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 12 12 12 153 153 148 246 239 193 249 241 199 +161 161 162 9 9 9 84 84 84 108 110 110 25 25 25 153 153 148 +247 237 174 246 224 96 218 217 217 165 165 165 182 183 184 193 193 194 +114 115 115 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 4 4 4 74 74 74 181 181 181 7 7 7 7 7 7 +110 114 114 200 200 197 7 7 7 7 7 7 60 60 60 209 210 210 +7 7 7 7 7 7 146 146 147 248 234 156 248 234 156 177 177 174 +7 7 7 118 118 118 193 193 194 7 7 7 84 84 84 232 232 233 +8 8 8 7 7 7 209 210 210 221 218 200 193 187 162 219 219 219 +200 200 197 7 7 7 7 7 7 7 7 7 7 7 7 95 97 97 +251 252 252 254 254 254 252 253 253 118 118 118 29 29 30 247 248 249 +252 252 253 227 227 227 16 16 16 7 7 7 7 7 7 7 7 7 +100 103 103 218 217 217 219 218 214 7 7 7 7 7 7 7 7 7 +7 7 7 21 21 22 185 185 184 246 239 193 248 234 156 240 230 197 +60 60 60 194 194 184 246 239 193 249 241 199 137 136 134 10 10 10 +171 168 154 248 234 156 248 234 156 226 226 219 209 210 210 249 241 199 +28 28 28 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 13 13 13 108 110 110 146 146 147 7 7 7 7 7 7 +167 168 167 140 140 139 7 7 7 7 7 7 120 121 122 146 146 147 +7 7 7 7 7 7 194 194 184 240 219 129 247 237 174 95 97 97 +7 7 7 95 97 97 90 87 86 7 7 7 118 118 118 176 177 177 +7 7 7 28 28 28 248 248 249 44 44 45 7 7 7 167 168 167 +140 140 139 7 7 7 36 36 36 74 74 74 7 7 7 65 64 64 +251 252 253 254 254 254 251 252 252 81 81 82 108 110 110 251 252 252 +251 251 252 127 127 126 7 7 7 7 7 7 8 8 8 140 140 139 +181 181 181 140 140 139 221 218 200 7 7 7 7 7 7 7 7 7 +34 34 35 209 210 210 231 231 231 246 239 193 247 237 174 194 194 184 +227 227 227 249 241 199 240 219 129 248 234 156 153 153 148 7 7 7 +13 13 13 185 185 184 248 234 156 245 218 76 245 216 51 245 214 38 +31 31 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 31 31 31 153 154 155 89 90 91 7 7 7 8 8 8 +232 232 233 82 82 81 7 7 7 7 7 7 179 180 181 89 90 91 +7 7 7 24 24 24 243 235 220 248 234 156 240 230 197 20 20 20 +7 7 7 7 7 7 7 7 7 7 7 7 149 149 150 118 118 118 +7 7 7 90 87 86 229 229 230 7 7 7 7 7 7 229 229 230 +82 82 81 7 7 7 95 97 97 100 103 103 7 7 7 34 34 35 +251 252 252 253 253 254 251 251 252 47 47 47 193 193 194 251 252 252 +239 239 240 23 23 23 7 7 7 13 13 13 165 165 165 234 234 234 +149 149 150 146 114 101 200 200 197 7 7 7 7 7 7 52 53 53 +227 227 227 167 168 167 16 16 16 214 196 166 248 234 156 243 235 220 +219 219 219 156 155 156 247 237 174 246 239 193 75 75 76 7 7 7 +60 60 60 227 227 227 243 235 220 240 219 129 245 218 76 245 213 29 +16 16 16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 1 49 50 50 185 185 184 33 33 34 7 7 7 10 11 11 +56 56 56 16 16 16 7 7 7 10 10 10 237 237 238 26 27 27 +7 7 7 55 55 55 185 185 184 221 218 200 167 168 167 7 7 7 +20 20 20 39 39 39 10 11 11 7 7 7 181 181 181 58 58 58 +7 7 7 103 103 103 133 133 133 7 7 7 44 44 44 247 248 249 +24 24 24 7 7 7 156 155 156 129 130 130 7 7 7 9 9 9 +244 245 245 252 253 253 237 237 238 34 34 35 248 248 249 251 251 252 +161 161 162 7 7 7 24 24 24 187 187 188 212 211 212 67 70 70 +187 187 188 173 170 143 209 206 202 10 10 10 95 97 97 237 237 238 +129 130 130 8 8 8 89 90 91 246 239 193 247 237 174 177 177 174 +17 18 18 137 136 134 249 241 199 219 218 214 10 10 10 95 97 97 +243 243 243 150 151 151 31 31 31 221 218 200 240 219 129 53 54 54 +3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +4 4 4 72 71 71 182 183 184 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 12 12 12 161 161 162 209 210 210 7 7 7 +7 7 7 7 7 7 7 7 7 187 187 188 82 82 81 7 7 7 +146 146 147 247 248 249 17 18 18 7 7 7 212 211 212 47 47 47 +7 7 7 7 7 7 7 7 7 8 8 8 146 146 147 205 205 205 +7 7 7 7 7 7 214 214 215 156 155 156 7 7 7 7 7 7 +218 217 217 251 252 252 186 186 187 110 114 114 249 250 251 248 248 249 +75 75 76 34 34 35 205 205 205 129 130 130 16 16 16 7 7 7 +156 155 156 214 196 166 240 230 197 243 243 241 227 227 227 74 74 74 +7 7 7 29 29 30 226 226 219 249 241 199 175 173 165 14 14 14 +9 9 9 221 218 200 246 239 193 153 153 148 146 146 147 246 247 248 +110 114 114 7 7 7 7 7 7 42 42 43 193 193 194 95 97 97 +19 19 19 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +6 6 6 84 84 84 140 142 143 7 7 7 7 7 7 7 7 7 +7 7 7 20 20 20 177 177 174 249 241 199 149 149 150 7 7 7 +7 7 7 7 7 7 10 11 11 226 226 219 13 13 13 8 8 8 +219 218 214 219 218 214 7 7 7 8 8 8 238 238 236 200 200 197 +13 13 13 7 7 7 13 13 13 161 161 162 243 235 220 146 146 147 +7 7 7 29 29 30 232 232 233 176 177 177 7 7 7 7 7 7 +182 183 184 237 237 238 129 130 130 167 168 167 176 177 177 202 202 203 +10 11 11 95 97 97 44 44 45 7 7 7 7 7 7 7 7 7 +75 75 76 226 226 219 243 235 220 156 155 156 24 24 24 7 7 7 +7 7 7 176 177 177 247 247 246 200 200 197 17 18 18 7 7 7 +49 50 50 246 239 193 248 234 156 251 248 240 239 239 240 84 84 84 +7 7 7 7 7 7 7 7 7 7 7 7 60 60 60 187 187 188 +84 84 84 14 14 14 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +4 4 4 53 54 54 137 136 134 156 155 156 161 161 162 161 161 162 +167 168 167 239 223 156 240 219 129 246 226 108 239 223 156 239 223 156 +239 223 156 239 223 156 214 196 166 239 223 156 193 187 162 193 187 162 +248 234 156 239 223 156 193 187 162 193 187 162 248 234 156 248 234 156 +214 196 166 193 187 162 214 196 166 248 234 156 240 219 129 214 196 166 +193 187 162 193 187 162 171 168 154 146 146 147 137 136 134 137 136 134 +161 161 162 209 210 210 65 64 64 202 202 203 179 180 181 140 140 139 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 60 60 60 39 39 39 7 7 7 7 7 7 7 7 7 +66 66 66 249 250 251 202 202 203 16 16 16 7 7 7 7 7 7 +23 23 23 243 235 220 246 239 193 226 226 219 52 53 53 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 75 75 76 +176 177 177 66 66 66 9 9 9 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 10 10 10 28 28 29 34 34 35 36 36 36 36 36 36 +44 44 45 146 114 101 241 207 50 241 207 50 241 207 50 241 211 63 +241 211 63 241 211 63 241 211 63 241 211 63 241 211 63 245 216 51 +245 216 51 245 216 51 241 211 63 241 211 63 245 216 51 241 211 63 +245 218 76 245 218 76 245 216 51 245 215 41 245 214 38 241 207 50 +241 211 63 201 147 55 88 79 47 29 29 30 34 34 35 42 42 43 +103 103 103 191 190 190 75 75 76 196 196 197 200 200 197 65 64 64 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +90 87 86 146 146 147 19 19 19 7 7 7 7 7 7 7 7 7 +7 7 7 90 87 86 140 140 139 31 31 31 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +103 103 103 161 161 162 53 54 54 7 7 7 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 12 12 12 50 51 51 146 114 101 180 121 62 199 129 48 +201 147 55 213 157 40 213 157 40 230 165 41 226 179 40 226 179 40 +238 192 33 241 205 27 244 209 25 244 210 23 244 212 23 245 211 23 +245 211 23 245 211 23 245 211 23 244 209 25 238 204 29 226 179 40 +213 157 40 199 129 48 54 42 32 0 0 0 4 6 6 44 44 45 +150 151 151 129 130 130 137 136 134 205 205 205 202 202 203 8 8 8 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 129 130 130 146 146 147 47 47 47 4 4 4 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 2 2 2 12 12 12 28 28 29 49 50 50 +74 74 74 108 96 91 180 121 62 180 121 62 199 129 48 201 147 55 +213 157 40 230 165 41 226 179 40 238 192 33 241 205 27 241 205 27 +243 206 27 243 206 27 241 205 27 238 204 29 226 179 40 213 157 40 +199 129 48 199 129 48 21 19 17 65 64 64 103 103 103 167 168 167 +202 202 203 24 24 24 193 193 194 229 229 230 140 140 139 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 8 8 8 156 155 156 133 133 133 36 36 36 3 3 3 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +4 4 4 10 11 11 21 21 22 39 39 39 60 60 60 108 96 91 +180 121 62 199 129 48 199 129 48 213 157 40 230 165 41 226 179 40 +226 179 40 226 179 40 226 179 40 226 179 40 213 157 40 199 129 48 +180 121 62 99 91 79 72 71 71 56 56 56 129 130 130 167 168 167 +21 21 22 17 18 18 231 231 231 229 229 230 52 53 53 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 13 13 13 176 177 177 120 121 122 33 33 34 +2 2 2 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 8 8 8 +21 21 22 47 47 47 99 91 79 180 121 62 199 129 48 199 129 48 +201 147 55 213 157 40 213 157 40 201 147 55 199 129 48 180 121 62 +99 91 79 26 26 27 9 9 9 60 60 60 186 186 187 31 31 31 +7 7 7 60 60 60 243 243 243 209 210 210 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 +7 7 7 7 7 7 7 7 7 26 27 27 193 193 194 108 110 110 +22 22 22 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 8 8 8 24 24 24 58 58 58 108 96 91 +180 121 62 180 121 62 180 121 62 180 121 62 180 121 62 72 71 71 +15 15 15 0 0 0 4 6 6 75 75 76 156 155 156 24 24 24 +24 24 24 108 107 107 232 232 233 137 136 134 24 24 24 24 24 24 +24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 +24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 +24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 +24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 +24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 24 +24 24 24 24 24 24 24 24 24 24 24 24 58 58 58 176 177 177 +60 60 60 3 3 3 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 12 12 12 +26 27 27 44 44 44 55 55 55 50 51 51 29 29 30 8 8 8 +0 0 0 0 0 0 3 3 3 47 47 47 127 127 126 150 151 151 +150 151 151 140 142 143 129 130 130 140 142 143 150 151 151 150 151 151 +150 151 151 150 151 151 150 151 151 150 151 151 150 151 151 150 151 151 +150 151 151 150 151 151 153 154 155 161 161 162 165 165 165 167 168 167 +177 177 174 167 168 167 161 161 162 156 155 156 150 151 151 150 151 151 +150 151 151 150 151 151 150 151 151 150 151 151 150 151 151 150 151 151 +150 151 151 150 151 151 150 151 151 150 151 151 150 151 151 150 151 151 +150 151 151 150 151 151 150 151 151 150 151 151 149 149 150 127 127 126 +44 44 45 2 2 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 2 2 2 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 7 7 21 21 22 25 25 26 +25 25 26 24 24 24 20 20 20 23 23 24 25 25 26 26 26 27 +26 26 27 26 26 27 26 26 27 26 26 27 26 26 27 26 26 27 +26 26 27 26 26 27 26 26 27 26 26 27 26 26 27 26 27 27 +28 28 29 26 27 27 26 26 27 26 26 27 26 26 27 26 26 27 +26 26 27 26 26 27 26 26 27 26 26 27 26 26 27 26 26 27 +26 26 27 26 26 27 26 26 27 26 26 27 26 26 27 26 26 27 +26 26 27 26 26 27 26 26 27 26 26 27 25 25 26 21 21 22 +7 7 7 0 0 0 diff --git a/drivers/video/logo/logo_blackfin_vga16.ppm b/drivers/video/logo/logo_blackfin_vga16.ppm new file mode 100644 index 0000000..1352b02 --- /dev/null +++ b/drivers/video/logo/logo_blackfin_vga16.ppm @@ -0,0 +1,1127 @@ +P3 +# This was generated by the GIMP & Netpbm tools +# gimp linux_bf.svg (create 80x80 save as linux_bf.ppm) +# ppmquant -mapfile clut_vga16.ppm linux_bf.ppm | pnmnoraw > logo_blackfin_vga16.ppm +# +80 80 +255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +170 170 170 85 85 85 85 85 85 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 255 255 255 +255 255 255 255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 +0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +255 255 255 170 170 170 85 85 85 170 170 170 255 255 255 255 255 255 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 85 85 85 +85 85 85 170 170 170 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +255 255 255 85 85 85 170 170 170 170 170 170 255 255 255 255 255 255 +85 85 85 85 85 85 170 170 170 255 255 255 170 170 170 0 0 0 +170 170 170 170 170 170 255 255 255 255 255 255 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +255 255 255 0 0 0 85 85 85 170 170 170 170 170 170 255 255 255 +0 0 0 85 85 85 85 85 85 255 255 255 85 85 85 0 0 0 +0 0 0 85 85 85 170 170 170 255 255 255 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +255 255 255 85 85 85 0 0 0 0 0 0 255 85 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 85 85 85 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +170 170 170 255 255 255 0 0 0 255 85 85 170 85 0 170 85 0 +255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 255 255 85 +0 0 0 85 85 85 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 255 255 255 255 85 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 255 85 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +170 85 0 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 170 85 0 85 85 85 255 255 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +255 85 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +170 85 0 85 85 85 255 255 85 255 255 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +170 85 0 170 85 0 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 170 85 0 +170 85 0 255 255 85 255 255 85 255 85 85 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 170 85 0 170 85 0 170 85 0 255 255 85 255 255 85 +255 255 85 255 85 85 170 85 0 170 85 0 170 85 0 255 255 85 +255 255 85 255 255 85 255 85 85 170 170 170 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 170 170 170 170 85 0 170 85 0 170 85 0 170 85 0 +170 85 0 170 85 0 170 85 0 255 255 85 255 255 85 255 255 85 +255 85 85 170 170 170 255 255 255 255 255 255 85 85 85 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +170 170 170 170 170 170 170 170 170 170 85 0 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 85 85 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +170 170 170 255 255 255 255 255 255 170 170 170 170 85 0 255 85 85 +255 85 85 255 85 85 255 85 85 255 85 85 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 0 0 0 0 0 0 85 85 85 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 170 170 170 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 255 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 +170 170 170 170 170 170 170 170 170 255 255 255 0 0 0 85 85 85 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 170 170 170 170 170 170 255 255 255 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 170 170 170 85 85 85 170 170 170 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 170 170 170 255 255 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +170 170 170 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 +170 170 170 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 +170 170 170 0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 170 170 170 255 255 255 255 255 255 +170 170 170 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 +255 255 85 255 255 85 0 0 0 85 85 85 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 85 85 85 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 85 170 170 170 +85 85 85 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 170 170 170 170 170 170 170 170 170 +255 255 255 85 85 85 0 0 0 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 255 255 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 0 0 0 85 85 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 0 0 0 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 255 255 255 255 255 255 255 255 255 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 255 255 85 255 255 85 255 255 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 170 170 170 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 +0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 +85 85 85 0 0 0 255 255 85 255 255 85 255 255 85 255 255 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 255 255 85 +255 255 85 255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 +255 255 85 85 85 85 170 170 170 170 170 170 170 170 170 170 170 170 +255 255 255 255 255 255 170 170 170 170 170 170 170 170 170 255 255 255 +255 255 255 170 170 170 170 170 170 255 255 255 0 0 0 0 0 0 +0 0 0 85 85 85 255 255 255 255 255 255 255 255 255 85 85 85 +85 85 85 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 255 255 85 255 255 85 255 255 85 255 255 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 +0 0 0 0 0 0 255 255 255 85 85 85 0 0 0 0 0 0 +255 255 255 85 85 85 0 0 0 0 0 0 255 255 255 255 255 85 +255 255 85 170 170 170 0 0 0 0 0 0 0 0 0 170 170 170 +255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 85 85 85 0 0 0 85 85 85 255 255 255 +85 85 85 0 0 0 85 85 85 255 255 255 0 0 0 0 0 0 +0 0 0 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 85 85 85 0 0 0 0 0 0 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 255 255 85 255 255 85 255 255 85 255 255 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 +0 0 0 85 85 85 255 255 255 0 0 0 0 0 0 85 85 85 +255 255 255 0 0 0 0 0 0 85 85 85 255 255 85 255 255 85 +255 255 85 85 85 85 0 0 0 0 0 0 0 0 0 170 170 170 +255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 0 0 0 0 0 0 170 170 170 170 170 170 +0 0 0 0 0 0 255 255 255 255 255 255 0 0 0 85 85 85 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 85 85 85 0 0 0 85 85 85 255 255 255 255 255 255 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 255 255 255 255 255 85 255 255 85 255 255 85 +255 255 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 +0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 170 170 170 +170 170 170 0 0 0 0 0 0 170 170 170 255 255 85 255 255 85 +255 255 255 0 0 0 85 85 85 85 85 85 0 0 0 170 170 170 +255 255 255 0 0 0 0 0 0 170 170 170 85 85 85 0 0 0 +85 85 85 170 170 170 0 0 0 0 0 0 170 170 170 0 0 0 +0 0 0 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +85 85 85 0 0 0 85 85 85 255 255 255 255 255 255 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 255 255 255 255 255 85 255 255 85 +255 255 85 170 85 0 0 0 0 85 85 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 +170 170 170 0 0 0 0 0 0 170 170 170 255 255 85 255 255 85 +170 170 170 0 0 0 170 170 170 85 85 85 0 0 0 255 255 255 +170 170 170 0 0 0 0 0 0 255 255 255 0 0 0 0 0 0 +170 170 170 170 170 170 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 +255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 255 255 85 +255 255 85 255 255 85 255 255 255 170 170 170 170 170 170 255 255 255 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 255 255 255 255 255 +85 85 85 0 0 0 0 0 0 255 255 255 255 255 85 255 255 85 +85 85 85 0 0 0 255 255 255 85 85 85 0 0 0 255 255 255 +85 85 85 0 0 0 85 85 85 255 255 255 85 85 85 85 85 85 +255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 85 85 85 +255 255 255 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 +170 170 170 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 +255 255 85 255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 +0 0 0 0 0 0 85 85 85 255 255 85 255 255 85 255 255 255 +0 0 0 85 85 85 255 255 255 0 0 0 85 85 85 255 255 255 +85 85 85 0 0 0 170 170 170 255 255 255 170 170 170 170 170 170 +255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +255 255 255 255 255 255 255 255 255 170 170 170 0 0 0 170 170 170 +255 255 255 255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 255 255 255 +170 170 170 0 0 0 85 85 85 85 85 85 0 0 0 170 170 170 +255 255 85 255 255 85 255 255 255 170 170 170 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 +85 85 85 170 170 170 0 0 0 0 0 0 85 85 85 170 170 170 +0 0 0 0 0 0 170 170 170 255 255 85 255 255 85 170 170 170 +0 0 0 85 85 85 170 170 170 0 0 0 85 85 85 255 255 255 +0 0 0 0 0 0 170 170 170 170 170 170 170 170 170 255 255 255 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 255 255 255 +255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 255 255 85 255 255 255 +85 85 85 170 170 170 255 255 255 255 255 255 170 170 170 0 0 0 +170 170 170 255 255 85 255 255 85 255 255 255 170 170 170 255 255 255 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 +170 170 170 170 170 170 0 0 0 0 0 0 85 85 85 170 170 170 +0 0 0 0 0 0 170 170 170 255 255 85 255 255 255 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 170 170 170 +0 0 0 0 0 0 255 255 255 85 85 85 0 0 0 170 170 170 +170 170 170 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +255 255 255 255 255 255 255 255 255 85 85 85 85 85 85 255 255 255 +255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 170 170 170 +170 170 170 170 170 170 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 170 170 170 255 255 255 255 255 255 255 255 85 170 170 170 +255 255 255 255 255 255 255 255 85 255 255 85 170 170 170 0 0 0 +0 0 0 170 170 170 255 255 85 255 255 85 255 255 85 255 255 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 85 85 85 0 0 0 0 0 0 +255 255 255 85 85 85 0 0 0 0 0 0 170 170 170 85 85 85 +0 0 0 0 0 0 255 255 255 255 255 85 255 255 255 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 +0 0 0 85 85 85 255 255 255 0 0 0 0 0 0 255 255 255 +85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 85 85 85 170 170 170 255 255 255 +255 255 255 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 +170 170 170 85 85 85 170 170 170 0 0 0 0 0 0 85 85 85 +255 255 255 170 170 170 0 0 0 170 170 170 255 255 85 255 255 255 +255 255 255 170 170 170 255 255 255 255 255 255 85 85 85 0 0 0 +85 85 85 255 255 255 255 255 255 255 255 85 255 255 85 255 255 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 255 255 255 0 0 0 +0 0 0 85 85 85 170 170 170 255 255 255 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 +0 0 0 85 85 85 170 170 170 0 0 0 85 85 85 255 255 255 +0 0 0 0 0 0 170 170 170 170 170 170 0 0 0 0 0 0 +255 255 255 255 255 255 255 255 255 0 0 0 255 255 255 255 255 255 +170 170 170 0 0 0 0 0 0 170 170 170 255 255 255 85 85 85 +170 170 170 170 170 170 170 170 170 0 0 0 85 85 85 255 255 255 +170 170 170 0 0 0 85 85 85 255 255 255 255 255 85 170 170 170 +0 0 0 170 170 170 255 255 255 255 255 255 0 0 0 85 85 85 +255 255 255 170 170 170 0 0 0 170 170 170 255 255 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 0 0 0 +170 170 170 255 255 255 0 0 0 0 0 0 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 +0 0 0 0 0 0 255 255 255 170 170 170 0 0 0 0 0 0 +255 255 255 255 255 255 170 170 170 85 85 85 255 255 255 255 255 255 +85 85 85 0 0 0 170 170 170 170 170 170 0 0 0 0 0 0 +170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 85 85 85 +0 0 0 0 0 0 255 255 255 255 255 255 170 170 170 0 0 0 +0 0 0 170 170 170 255 255 255 170 170 170 170 170 170 255 255 255 +85 85 85 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 255 255 255 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 255 255 255 0 0 0 0 0 0 +255 255 255 255 255 255 0 0 0 0 0 0 255 255 255 170 170 170 +0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 170 170 170 +0 0 0 0 0 0 255 255 255 170 170 170 0 0 0 0 0 0 +170 170 170 255 255 255 170 170 170 170 170 170 170 170 170 170 170 170 +0 0 0 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 170 170 170 255 255 255 170 170 170 0 0 0 0 0 0 +85 85 85 255 255 255 255 255 85 255 255 255 255 255 255 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 85 255 255 85 255 255 85 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 255 255 85 +170 170 170 170 170 170 170 170 170 255 255 85 255 255 85 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 85 85 85 170 170 170 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 85 85 85 170 170 170 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 170 85 0 +170 85 0 255 85 85 255 85 85 255 85 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 85 85 170 85 0 85 85 85 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 170 85 0 170 85 0 170 85 0 170 85 0 +255 85 85 255 85 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 85 85 +170 85 0 170 85 0 0 0 0 85 85 85 85 85 85 170 170 170 +170 170 170 0 0 0 170 170 170 255 255 255 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +170 85 0 170 85 0 170 85 0 255 85 85 255 85 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 85 85 170 85 0 +170 85 0 85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 +0 0 0 0 0 0 255 255 255 255 255 255 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 170 85 0 170 85 0 170 85 0 +170 85 0 255 85 85 255 85 85 255 85 85 170 85 0 170 85 0 +85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 +0 0 0 85 85 85 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 +0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +170 85 0 170 85 0 170 85 0 170 85 0 170 85 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 +0 0 0 85 85 85 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 +85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 -- cgit v1.1 From 3fc957721d18c93662f7d4dab455b80f53dd2641 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 14 May 2008 16:05:49 -0700 Subject: lib: create common ascii hex array Add a common hex array in hexdump.c so everyone can use it. Add a common hi/lo helper to avoid the shifting masking that is done to get the upper and lower nibbles of a byte value. Pull the pack_hex_byte helper from kgdb as it is opencoded many places in the tree that will be consolidated. Signed-off-by: Harvey Harrison Acked-by: Paul Mundt Cc: Jason Wessel Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/kernel/kgdb_stub.c | 8 -------- drivers/pnp/support.c | 8 ++++---- include/linux/kernel.h | 12 +++++++++++- kernel/kgdb.c | 8 -------- lib/hexdump.c | 7 +++++-- 5 files changed, 20 insertions(+), 23 deletions(-) diff --git a/arch/sh/kernel/kgdb_stub.c b/arch/sh/kernel/kgdb_stub.c index d453c3a..832641bb 100644 --- a/arch/sh/kernel/kgdb_stub.c +++ b/arch/sh/kernel/kgdb_stub.c @@ -330,14 +330,6 @@ static char *ebin_to_mem(const char *buf, char *mem, int count) return mem; } -/* Pack a hex byte */ -static char *pack_hex_byte(char *pkt, int byte) -{ - *pkt++ = hexchars[(byte >> 4) & 0xf]; - *pkt++ = hexchars[(byte & 0xf)]; - return pkt; -} - /* Scan for the start char '$', read the packet and check the checksum */ static void get_packet(char *buffer, int buflen) { diff --git a/drivers/pnp/support.c b/drivers/pnp/support.c index 3eba85e..95b076c 100644 --- a/drivers/pnp/support.c +++ b/drivers/pnp/support.c @@ -45,10 +45,10 @@ void pnp_eisa_id_to_string(u32 id, char *str) str[0] = 'A' + ((id >> 26) & 0x3f) - 1; str[1] = 'A' + ((id >> 21) & 0x1f) - 1; str[2] = 'A' + ((id >> 16) & 0x1f) - 1; - str[3] = hex_asc((id >> 12) & 0xf); - str[4] = hex_asc((id >> 8) & 0xf); - str[5] = hex_asc((id >> 4) & 0xf); - str[6] = hex_asc((id >> 0) & 0xf); + str[3] = hex_asc_hi(id >> 8); + str[4] = hex_asc_lo(id >> 8); + str[5] = hex_asc_hi(id); + str[6] = hex_asc_lo(id); str[7] = '\0'; } diff --git a/include/linux/kernel.h b/include/linux/kernel.h index 4d46e29..792bf0a 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -276,7 +276,17 @@ extern void print_hex_dump(const char *level, const char *prefix_str, const void *buf, size_t len, bool ascii); extern void print_hex_dump_bytes(const char *prefix_str, int prefix_type, const void *buf, size_t len); -#define hex_asc(x) "0123456789abcdef"[x] + +extern const char hex_asc[]; +#define hex_asc_lo(x) hex_asc[((x) & 0x0f)] +#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] + +static inline char *pack_hex_byte(char *buf, u8 byte) +{ + *buf++ = hex_asc_hi(byte); + *buf++ = hex_asc_lo(byte); + return buf; +} #define pr_emerg(fmt, arg...) \ printk(KERN_EMERG fmt, ##arg) diff --git a/kernel/kgdb.c b/kernel/kgdb.c index 39e31a0..14787de 100644 --- a/kernel/kgdb.c +++ b/kernel/kgdb.c @@ -346,14 +346,6 @@ static void put_packet(char *buffer) } } -static char *pack_hex_byte(char *pkt, u8 byte) -{ - *pkt++ = hexchars[byte >> 4]; - *pkt++ = hexchars[byte & 0xf]; - - return pkt; -} - /* * Convert the memory pointed to by mem into hex, placing result in buf. * Return a pointer to the last char put in buf (null). May return an error. diff --git a/lib/hexdump.c b/lib/hexdump.c index 3435465..f07c0db 100644 --- a/lib/hexdump.c +++ b/lib/hexdump.c @@ -12,6 +12,9 @@ #include #include +const char hex_asc[] = "0123456789abcdef"; +EXPORT_SYMBOL(hex_asc); + /** * hex_dump_to_buffer - convert a blob of data to "hex ASCII" in memory * @buf: data blob to dump @@ -93,8 +96,8 @@ void hex_dump_to_buffer(const void *buf, size_t len, int rowsize, for (j = 0; (j < rowsize) && (j < len) && (lx + 4) < linebuflen; j++) { ch = ptr[j]; - linebuf[lx++] = hex_asc(ch >> 4); - linebuf[lx++] = hex_asc(ch & 0x0f); + linebuf[lx++] = hex_asc_hi(ch); + linebuf[lx++] = hex_asc_lo(ch); linebuf[lx++] = ' '; } ascii_column = 3 * rowsize + 2; -- cgit v1.1 From fd8a4221ad76df700ff34875c9fbc42302aa4ba3 Mon Sep 17 00:00:00 2001 From: Geoff Levand Date: Wed, 14 May 2008 16:05:50 -0700 Subject: memory_hotplug: check for walk_memory_resource() failure in online_pages() Add a check to online_pages() to test for failure of walk_memory_resource(). This fixes a condition where a failure of walk_memory_resource() can lead to online_pages() returning success without the requested pages being onlined. Signed-off-by: Geoff Levand Cc: Yasunori Goto Cc: KAMEZAWA Hiroyuki Cc: Dave Hansen Cc: Keith Mannthey Cc: Christoph Lameter Cc: Paul Jackson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory_hotplug.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 988bd91..656ad1c 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -404,8 +404,15 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) if (!populated_zone(zone)) need_zonelists_rebuild = 1; - walk_memory_resource(pfn, nr_pages, &onlined_pages, + ret = walk_memory_resource(pfn, nr_pages, &onlined_pages, online_pages_range); + if (ret) { + printk(KERN_DEBUG "online_pages %lx at %lx failed\n", + nr_pages, pfn); + memory_notify(MEM_CANCEL_ONLINE, &arg); + return ret; + } + zone->present_pages += onlined_pages; zone->zone_pgdat->node_present_pages += onlined_pages; -- cgit v1.1 From 44c81433e8b05dbc85985d939046f10f95901184 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 14 May 2008 16:05:51 -0700 Subject: per_cpu: fix DEFINE_PER_CPU_SHARED_ALIGNED for modules Current module loader lookups ".data.percpu" ELF section to perform per_cpu relocation. But DEFINE_PER_CPU_SHARED_ALIGNED() uses another section (".data.percpu.shared_aligned"), currently only handled in vmlinux.lds, not by module loader. To correct this problem, instead of adding logic into module loader, or using at build time a module.lds file for all arches to group ".data.percpu.shared_aligned" into ".data.percpu", just use ".data.percpu" for modules. Alignment requirements are correctly handled by ld and module loader. Signed-off-by: Eric Dumazet Cc: Rusty Russell Cc: Fenghua Yu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/percpu.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/include/linux/percpu.h b/include/linux/percpu.h index d746a2a..4cdd393 100644 --- a/include/linux/percpu.h +++ b/include/linux/percpu.h @@ -13,8 +13,14 @@ __attribute__((__section__(".data.percpu"))) \ PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name +#ifdef MODULE +#define SHARED_ALIGNED_SECTION ".data.percpu" +#else +#define SHARED_ALIGNED_SECTION ".data.percpu.shared_aligned" +#endif + #define DEFINE_PER_CPU_SHARED_ALIGNED(type, name) \ - __attribute__((__section__(".data.percpu.shared_aligned"))) \ + __attribute__((__section__(SHARED_ALIGNED_SECTION))) \ PER_CPU_ATTRIBUTES __typeof__(type) per_cpu__##name \ ____cacheline_aligned_in_smp #else -- cgit v1.1 From 1c12c4cf9411eb130b245fa8d0fbbaf989477c7b Mon Sep 17 00:00:00 2001 From: Venki Pallipadi Date: Wed, 14 May 2008 16:05:51 -0700 Subject: mprotect: prevent alteration of the PAT bits There is a defect in mprotect, which lets the user change the page cache type bits by-passing the kernel reserve_memtype and free_memtype wrappers. Fix the problem by not letting mprotect change the PAT bits. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar Signed-off-by: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/asm-x86/pgtable.h | 16 +++++++++++++--- mm/mprotect.c | 11 ++++++++++- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h index 801b31f..55c3a0e 100644 --- a/include/asm-x86/pgtable.h +++ b/include/asm-x86/pgtable.h @@ -57,7 +57,8 @@ #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | \ _PAGE_DIRTY) -#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) +#define _PAGE_CHG_MASK (PTE_MASK | _PAGE_PCD | _PAGE_PWT | \ + _PAGE_ACCESSED | _PAGE_DIRTY) #define _PAGE_CACHE_MASK (_PAGE_PCD | _PAGE_PWT) #define _PAGE_CACHE_WB (0) @@ -288,12 +289,21 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) * Chop off the NX bit (if present), and add the NX portion of * the newprot (if present): */ - val &= _PAGE_CHG_MASK & ~_PAGE_NX; - val |= pgprot_val(newprot) & __supported_pte_mask; + val &= _PAGE_CHG_MASK; + val |= pgprot_val(newprot) & (~_PAGE_CHG_MASK) & __supported_pte_mask; return __pte(val); } +/* mprotect needs to preserve PAT bits when updating vm_page_prot */ +#define pgprot_modify pgprot_modify +static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot) +{ + pgprotval_t preservebits = pgprot_val(oldprot) & _PAGE_CHG_MASK; + pgprotval_t addbits = pgprot_val(newprot); + return __pgprot(preservebits | addbits); +} + #define pte_pgprot(x) __pgprot(pte_val(x) & (0xfff | _PAGE_NX)) #define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask) diff --git a/mm/mprotect.c b/mm/mprotect.c index 4de5468..a5bf31c 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -26,6 +26,13 @@ #include #include +#ifndef pgprot_modify +static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot) +{ + return newprot; +} +#endif + static void change_pte_range(struct mm_struct *mm, pmd_t *pmd, unsigned long addr, unsigned long end, pgprot_t newprot, int dirty_accountable) @@ -192,7 +199,9 @@ success: * held in write mode. */ vma->vm_flags = newflags; - vma->vm_page_prot = vm_get_page_prot(newflags); + vma->vm_page_prot = pgprot_modify(vma->vm_page_prot, + vm_get_page_prot(newflags)); + if (vma_wants_writenotify(vma)) { vma->vm_page_prot = vm_get_page_prot(newflags & ~VM_SHARED); dirty_accountable = 1; -- cgit v1.1 From 76cdd58e558669366adfaded436fda01b30cce3e Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 14 May 2008 16:05:52 -0700 Subject: memory_hotplug: always initialize pageblock bitmap Trying to online a new memory section that was added via memory hotplug sometimes results in crashes when the new pages are added via __free_page. Reason for that is that the pageblock bitmap isn't initialized and hence contains random stuff. That means that get_pageblock_migratetype() returns also random stuff and therefore list_add(&page->lru, &zone->free_area[order].free_list[migratetype]); in __free_one_page() tries to do a list_add to something that isn't even necessarily a list. This happens since 86051ca5eaf5e560113ec7673462804c54284456 ("mm: fix usemap initialization") which makes sure that the pageblock bitmap gets only initialized for pages present in a zone. Unfortunately for hot-added memory the zones "grow" after the memmap and the pageblock memmap have been initialized. Which means that the new pages have an unitialized bitmap. To solve this the calls to grow_zone_span() and grow_pgdat_span() are moved to __add_zone() just before the initialization happens. The patch also moves the two functions since __add_zone() is the only caller and I didn't want to add a forward declaration. Signed-off-by: Heiko Carstens Cc: Andy Whitcroft Cc: Dave Hansen Cc: Gerald Schaefer Cc: KAMEZAWA Hiroyuki Cc: Yasunori Goto Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/memory_hotplug.c | 83 ++++++++++++++++++++++++++++------------------------- mm/page_alloc.c | 3 +- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index 656ad1c..833f854 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -159,17 +159,58 @@ void register_page_bootmem_info_node(struct pglist_data *pgdat) } #endif /* !CONFIG_SPARSEMEM_VMEMMAP */ +static void grow_zone_span(struct zone *zone, unsigned long start_pfn, + unsigned long end_pfn) +{ + unsigned long old_zone_end_pfn; + + zone_span_writelock(zone); + + old_zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages; + if (start_pfn < zone->zone_start_pfn) + zone->zone_start_pfn = start_pfn; + + zone->spanned_pages = max(old_zone_end_pfn, end_pfn) - + zone->zone_start_pfn; + + zone_span_writeunlock(zone); +} + +static void grow_pgdat_span(struct pglist_data *pgdat, unsigned long start_pfn, + unsigned long end_pfn) +{ + unsigned long old_pgdat_end_pfn = + pgdat->node_start_pfn + pgdat->node_spanned_pages; + + if (start_pfn < pgdat->node_start_pfn) + pgdat->node_start_pfn = start_pfn; + + pgdat->node_spanned_pages = max(old_pgdat_end_pfn, end_pfn) - + pgdat->node_start_pfn; +} + static int __add_zone(struct zone *zone, unsigned long phys_start_pfn) { struct pglist_data *pgdat = zone->zone_pgdat; int nr_pages = PAGES_PER_SECTION; int nid = pgdat->node_id; int zone_type; + unsigned long flags; zone_type = zone - pgdat->node_zones; - if (!zone->wait_table) - return init_currently_empty_zone(zone, phys_start_pfn, - nr_pages, MEMMAP_HOTPLUG); + if (!zone->wait_table) { + int ret; + + ret = init_currently_empty_zone(zone, phys_start_pfn, + nr_pages, MEMMAP_HOTPLUG); + if (ret) + return ret; + } + pgdat_resize_lock(zone->zone_pgdat, &flags); + grow_zone_span(zone, phys_start_pfn, phys_start_pfn + nr_pages); + grow_pgdat_span(zone->zone_pgdat, phys_start_pfn, + phys_start_pfn + nr_pages); + pgdat_resize_unlock(zone->zone_pgdat, &flags); memmap_init_zone(nr_pages, nid, zone_type, phys_start_pfn, MEMMAP_HOTPLUG); return 0; @@ -295,36 +336,6 @@ int __remove_pages(struct zone *zone, unsigned long phys_start_pfn, } EXPORT_SYMBOL_GPL(__remove_pages); -static void grow_zone_span(struct zone *zone, - unsigned long start_pfn, unsigned long end_pfn) -{ - unsigned long old_zone_end_pfn; - - zone_span_writelock(zone); - - old_zone_end_pfn = zone->zone_start_pfn + zone->spanned_pages; - if (start_pfn < zone->zone_start_pfn) - zone->zone_start_pfn = start_pfn; - - zone->spanned_pages = max(old_zone_end_pfn, end_pfn) - - zone->zone_start_pfn; - - zone_span_writeunlock(zone); -} - -static void grow_pgdat_span(struct pglist_data *pgdat, - unsigned long start_pfn, unsigned long end_pfn) -{ - unsigned long old_pgdat_end_pfn = - pgdat->node_start_pfn + pgdat->node_spanned_pages; - - if (start_pfn < pgdat->node_start_pfn) - pgdat->node_start_pfn = start_pfn; - - pgdat->node_spanned_pages = max(old_pgdat_end_pfn, end_pfn) - - pgdat->node_start_pfn; -} - void online_page(struct page *page) { totalram_pages++; @@ -363,7 +374,6 @@ static int online_pages_range(unsigned long start_pfn, unsigned long nr_pages, int online_pages(unsigned long pfn, unsigned long nr_pages) { - unsigned long flags; unsigned long onlined_pages = 0; struct zone *zone; int need_zonelists_rebuild = 0; @@ -391,11 +401,6 @@ int online_pages(unsigned long pfn, unsigned long nr_pages) * memory_block->state_mutex. */ zone = page_zone(pfn_to_page(pfn)); - pgdat_resize_lock(zone->zone_pgdat, &flags); - grow_zone_span(zone, pfn, pfn + nr_pages); - grow_pgdat_span(zone->zone_pgdat, pfn, pfn + nr_pages); - pgdat_resize_unlock(zone->zone_pgdat, &flags); - /* * If this zone is not populated, then it is not in zonelist. * This means the page allocator ignores this zone. diff --git a/mm/page_alloc.c b/mm/page_alloc.c index bdd5c43..6383557 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2862,8 +2862,6 @@ __meminit int init_currently_empty_zone(struct zone *zone, zone->zone_start_pfn = zone_start_pfn; - memmap_init(size, pgdat->node_id, zone_idx(zone), zone_start_pfn); - zone_init_free_lists(zone); return 0; @@ -3433,6 +3431,7 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat, ret = init_currently_empty_zone(zone, zone_start_pfn, size, MEMMAP_EARLY); BUG_ON(ret); + memmap_init(size, nid, j, zone_start_pfn); zone_start_pfn += size; } } -- cgit v1.1 From 4920916f728fe3c51f54c25ab7b3d271254aab5a Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 14 May 2008 16:05:53 -0700 Subject: char: select fw_loader by moxa Select FW_LOADER since moxa needs it, otherwise we face link problems such as: drivers/built-in.o: In function moxa_pci_probe':moxa.c:(.devinit.text+0x76d8): undefined reference to request_firmware' :moxa.c:(.devinit.text+0x7e6e): undefined reference to release_firmware' make: *** [.tmp_vmlinux1] Error 1 Reported-by: Philippe Roussel Signed-off-by: Jiri Slaby Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 5dce387..595a925 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig @@ -196,6 +196,7 @@ config ESPSERIAL config MOXA_INTELLIO tristate "Moxa Intellio support" depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI) + select FW_LOADER help Say Y here if you have a Moxa Intellio multiport serial card. -- cgit v1.1 From e7e72bf641b1fc7b9df6f40bd2c36dfccd8d647c Mon Sep 17 00:00:00 2001 From: Neil Brown Date: Wed, 14 May 2008 16:05:54 -0700 Subject: Remove blkdev warning triggered by using md As setting and clearing queue flags now requires that we hold a spinlock on the queue, and as blk_queue_stack_limits is called without that lock, get the lock inside blk_queue_stack_limits. For blk_queue_stack_limits to be able to find the right lock, each md personality needs to set q->queue_lock to point to the appropriate lock. Those personalities which didn't previously use a spin_lock, us q->__queue_lock. So always initialise that lock when allocated. With this in place, setting/clearing of the QUEUE_FLAG_PLUGGED bit will no longer cause warnings as it will be clear that the proper lock is held. Thanks to Dan Williams for review and fixing the silly bugs. Signed-off-by: NeilBrown Cc: Dan Williams Cc: Jens Axboe Cc: Alistair John Strachan Cc: Nick Piggin Cc: "Rafael J. Wysocki" Cc: Jacek Luczak Cc: Prakash Punnoor Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- block/blk-core.c | 5 ++--- block/blk-settings.c | 8 +++++++- drivers/md/linear.c | 1 + drivers/md/multipath.c | 1 + drivers/md/raid0.c | 1 + drivers/md/raid1.c | 4 +++- drivers/md/raid10.c | 4 +++- drivers/md/raid5.c | 1 + 8 files changed, 19 insertions(+), 6 deletions(-) diff --git a/block/blk-core.c b/block/blk-core.c index 2987fe4..6a9cc0d 100644 --- a/block/blk-core.c +++ b/block/blk-core.c @@ -482,6 +482,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id) kobject_init(&q->kobj, &blk_queue_ktype); mutex_init(&q->sysfs_lock); + spin_lock_init(&q->__queue_lock); return q; } @@ -544,10 +545,8 @@ blk_init_queue_node(request_fn_proc *rfn, spinlock_t *lock, int node_id) * if caller didn't supply a lock, they get per-queue locking with * our embedded lock */ - if (!lock) { - spin_lock_init(&q->__queue_lock); + if (!lock) lock = &q->__queue_lock; - } q->request_fn = rfn; q->prep_rq_fn = NULL; diff --git a/block/blk-settings.c b/block/blk-settings.c index bb93d4c..8dd8641 100644 --- a/block/blk-settings.c +++ b/block/blk-settings.c @@ -286,8 +286,14 @@ void blk_queue_stack_limits(struct request_queue *t, struct request_queue *b) t->max_hw_segments = min(t->max_hw_segments, b->max_hw_segments); t->max_segment_size = min(t->max_segment_size, b->max_segment_size); t->hardsect_size = max(t->hardsect_size, b->hardsect_size); - if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) + if (!t->queue_lock) + WARN_ON_ONCE(1); + else if (!test_bit(QUEUE_FLAG_CLUSTER, &b->queue_flags)) { + unsigned long flags; + spin_lock_irqsave(t->queue_lock, flags); queue_flag_clear(QUEUE_FLAG_CLUSTER, t); + spin_unlock_irqrestore(t->queue_lock, flags); + } } EXPORT_SYMBOL(blk_queue_stack_limits); diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 0b85117..1074824 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -250,6 +250,7 @@ static int linear_run (mddev_t *mddev) { linear_conf_t *conf; + mddev->queue->queue_lock = &mddev->queue->__queue_lock; conf = linear_conf(mddev, mddev->raid_disks); if (!conf) diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 42ee1a2..4f4d1f3 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -417,6 +417,7 @@ static int multipath_run (mddev_t *mddev) * bookkeeping area. [whatever we allocate in multipath_run(), * should be freed in multipath_stop()] */ + mddev->queue->queue_lock = &mddev->queue->__queue_lock; conf = kzalloc(sizeof(multipath_conf_t), GFP_KERNEL); mddev->private = conf; diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 818b482..914c04d 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -280,6 +280,7 @@ static int raid0_run (mddev_t *mddev) (mddev->chunk_size>>1)-1); blk_queue_max_sectors(mddev->queue, mddev->chunk_size >> 9); blk_queue_segment_boundary(mddev->queue, (mddev->chunk_size>>1) - 1); + mddev->queue->queue_lock = &mddev->queue->__queue_lock; conf = kmalloc(sizeof (raid0_conf_t), GFP_KERNEL); if (!conf) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 6778b7c..ac409b7 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1935,6 +1935,9 @@ static int run(mddev_t *mddev) if (!conf->r1bio_pool) goto out_no_mem; + spin_lock_init(&conf->device_lock); + mddev->queue->queue_lock = &conf->device_lock; + rdev_for_each(rdev, tmp, mddev) { disk_idx = rdev->raid_disk; if (disk_idx >= mddev->raid_disks @@ -1958,7 +1961,6 @@ static int run(mddev_t *mddev) } conf->raid_disks = mddev->raid_disks; conf->mddev = mddev; - spin_lock_init(&conf->device_lock); INIT_LIST_HEAD(&conf->retry_list); spin_lock_init(&conf->resync_lock); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index faf3d89..8536ede 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -2082,6 +2082,9 @@ static int run(mddev_t *mddev) goto out_free_conf; } + spin_lock_init(&conf->device_lock); + mddev->queue->queue_lock = &conf->device_lock; + rdev_for_each(rdev, tmp, mddev) { disk_idx = rdev->raid_disk; if (disk_idx >= mddev->raid_disks @@ -2103,7 +2106,6 @@ static int run(mddev_t *mddev) disk->head_position = 0; } - spin_lock_init(&conf->device_lock); INIT_LIST_HEAD(&conf->retry_list); spin_lock_init(&conf->resync_lock); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index ee0ea91..93fde48 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4257,6 +4257,7 @@ static int run(mddev_t *mddev) goto abort; } spin_lock_init(&conf->device_lock); + mddev->queue->queue_lock = &conf->device_lock; init_waitqueue_head(&conf->wait_for_stripe); init_waitqueue_head(&conf->wait_for_overlap); INIT_LIST_HEAD(&conf->handle_list); -- cgit v1.1 From 9ffee4cbc51907755809d98613d9e7133612803a Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 14 May 2008 16:05:58 -0700 Subject: tty_check_change(): avoid taking tasklist_lock while holding tty->ctrl_lock May 11 09:42:27 [kernel] [ 1104.496819] rarian-sk-get-c[5630]: segfault at 0 ip 7f478556caf0 sp 7fff8e3fe338 error 4 in libc-2.6.1.so[7f47854f9000+136000] May 11 10:59:48 [kernel] [ 2494.165792] May 11 10:59:48 [kernel] [ 2494.165794] ======================================================= May 11 10:59:48 [kernel] [ 2494.165801] [ INFO: possible circular locking dependency detected ] May 11 10:59:48 [kernel] [ 2494.165805] 2.6.26-rc1-00007-g91b3a7a #217 May 11 10:59:48 [kernel] [ 2494.165807] ------------------------------------------------------- May 11 10:59:48 [kernel] [ 2494.165809] less/7053 is trying to acquire lock: May 11 10:59:48 [kernel] [ 2494.165812] (tasklist_lock){..??}, at: [] is_current_pgrp_orphaned+0x15/0x50 May 11 10:59:48 [kernel] [ 2494.165821] May 11 10:59:48 [kernel] [ 2494.165822] but task is already holding lock: May 11 10:59:48 [kernel] [ 2494.165824] (&tty->ctrl_lock){....}, at: [] tty_check_change+0x61/0x110 May 11 10:59:48 [kernel] [ 2494.165831] May 11 10:59:48 [kernel] [ 2494.165832] which lock already depends on the new lock. May 11 10:59:48 [kernel] [ 2494.165833] May 11 10:59:48 [kernel] [ 2494.165835] May 11 10:59:48 [kernel] [ 2494.165836] the existing dependency chain (in reverse order) is: May 11 10:59:48 [kernel] [ 2494.165838] May 11 10:59:48 [kernel] [ 2494.165839] -> #2 (&tty->ctrl_lock){....}: May 11 10:59:48 [kernel] [ 2494.165843] [] __lock_acquire+0xf86/0x1080 May 11 10:59:48 [kernel] [ 2494.165851] [] lock_acquire+0x92/0xc0 May 11 10:59:48 [kernel] [ 2494.165858] [] _spin_lock_irqsave+0x40/0x60 May 11 10:59:48 [kernel] [ 2494.165866] [] __proc_set_tty+0x35/0xe0 May 11 10:59:48 [kernel] [ 2494.165873] [] tty_ioctl+0xbf4/0xfe0 May 11 10:59:48 [kernel] [ 2494.165880] [] vfs_ioctl+0x31/0x90 May 11 10:59:48 [kernel] [ 2494.165888] [] do_vfs_ioctl+0x73/0x2d0 May 11 10:59:48 [kernel] [ 2494.165895] [] sys_ioctl+0x4a/0x80 May 11 10:59:48 [kernel] [ 2494.165902] [] system_call_after_swapgs+0x7b/0x80 May 11 10:59:48 [kernel] [ 2494.165910] [] 0xffffffffffffffff May 11 10:59:48 [kernel] [ 2494.165924] May 11 10:59:48 [kernel] [ 2494.165925] -> #1 (&sighand->siglock){++..}: May 11 10:59:48 [kernel] [ 2494.165929] [] __lock_acquire+0xf86/0x1080 May 11 10:59:48 [kernel] [ 2494.165936] [] lock_acquire+0x92/0xc0 May 11 10:59:48 [kernel] [ 2494.165943] [] _spin_lock+0x2f/0x40 May 11 10:59:48 [kernel] [ 2494.165951] [] copy_process+0x973/0x1210 May 11 10:59:48 [kernel] [ 2494.165959] [] do_fork+0x82/0x2f0 May 11 10:59:48 [kernel] [ 2494.165967] [] kernel_thread+0x81/0xde May 11 10:59:48 [kernel] [ 2494.165974] [] child_rip+0xa/0x12 May 11 10:59:48 [kernel] [ 2494.165981] [] 0xffffffffffffffff May 11 10:59:48 [kernel] [ 2494.166038] May 11 10:59:48 [kernel] [ 2494.166039] -> #0 (tasklist_lock){..??}: May 11 10:59:48 [kernel] [ 2494.166043] [] __lock_acquire+0xd9b/0x1080 May 11 10:59:48 [kernel] [ 2494.166050] [] lock_acquire+0x92/0xc0 May 11 10:59:48 [kernel] [ 2494.166057] [] _read_lock+0x32/0x50 May 11 10:59:48 [kernel] [ 2494.166063] [] is_current_pgrp_orphaned+0x15/0x50 May 11 10:59:48 [kernel] [ 2494.166071] [] tty_check_change+0xb0/0x110 May 11 10:59:48 [kernel] [ 2494.166078] [] set_termios+0x1f/0x4c0 May 11 10:59:48 [kernel] [ 2494.166085] [] tty_mode_ioctl+0x279/0x3e0 May 11 10:59:48 [kernel] [ 2494.166092] [] n_tty_ioctl+0x3d/0x260 May 11 10:59:48 [kernel] [ 2494.166100] [] tty_ioctl+0x154/0xfe0 May 11 10:59:48 [kernel] [ 2494.166107] [] vfs_ioctl+0x31/0x90 May 11 10:59:48 [kernel] [ 2494.166114] [] do_vfs_ioctl+0x73/0x2d0 May 11 10:59:48 [kernel] [ 2494.166121] [] sys_ioctl+0x4a/0x80 May 11 10:59:48 [kernel] [ 2494.166128] [] system_call_after_swapgs+0x7b/0x80 May 11 10:59:48 [kernel] [ 2494.166135] [] 0xffffffffffffffff May 11 10:59:48 [kernel] [ 2494.166142] May 11 10:59:48 [kernel] [ 2494.166143] other info that might help us debug this: May 11 10:59:48 [kernel] [ 2494.166144] May 11 10:59:48 [kernel] [ 2494.166146] 1 lock held by less/7053: May 11 10:59:48 [kernel] [ 2494.166148] #0: (&tty->ctrl_lock){....}, at: [] tty_check_change+0x61/0x110 May 11 10:59:48 [kernel] [ 2494.166155] May 11 10:59:48 [kernel] [ 2494.166156] stack backtrace: May 11 10:59:48 [kernel] [ 2494.166159] Pid: 7053, comm: less Not tainted 2.6.26-rc1-00007-g91b3a7a #217 May 11 10:59:48 [kernel] [ 2494.166161] May 11 10:59:48 [kernel] [ 2494.166162] Call Trace: May 11 10:59:48 [kernel] [ 2494.166168] [] print_circular_bug_tail+0x83/0x90 May 11 10:59:48 [kernel] [ 2494.166172] [] ? print_circular_bug_entry+0x49/0x60 May 11 10:59:48 [kernel] [ 2494.166178] [] __lock_acquire+0xd9b/0x1080 May 11 10:59:48 [kernel] [ 2494.166184] [] ? is_current_pgrp_orphaned+0x15/0x50 May 11 10:59:48 [kernel] [ 2494.166189] [] lock_acquire+0x92/0xc0 May 11 10:59:48 [kernel] [ 2494.166206] [] tty_check_change+0xb0/0x110 May 11 10:59:48 [kernel] [ 2494.166211] [] set_termios+0x1f/0x4c0 May 11 10:59:48 [kernel] [ 2494.166216] [] ? tty_ldisc_try+0x23/0x60 May 11 10:59:48 [kernel] [ 2494.166220] [] ? tty_ldisc_try+0x44/0x60 May 11 10:59:48 [kernel] [ 2494.166224] [] ? _spin_unlock_irqrestore+0x65/0x80 May 11 10:59:48 [kernel] [ 2494.166230] [] tty_mode_ioctl+0x279/0x3e0 May 11 10:59:48 [kernel] [ 2494.166234] [] ? tty_ldisc_try+0x44/0x60 May 11 10:59:48 [kernel] [ 2494.166239] [] n_tty_ioctl+0x3d/0x260 May 11 10:59:48 [kernel] [ 2494.166244] [] tty_ioctl+0x154/0xfe0 May 11 10:59:48 [kernel] [ 2494.166249] [] ? __lock_acquire+0x39a/0x1080 May 11 10:59:48 [kernel] [ 2494.166256] [] ? __lock_acquire+0x39a/0x1080 May 11 10:59:48 [kernel] [ 2494.166263] [] ? __lock_acquire+0x39a/0x1080 May 11 10:59:48 [kernel] [ 2494.166269] [] vfs_ioctl+0x31/0x90 May 11 10:59:48 [kernel] [ 2494.166274] [] do_vfs_ioctl+0x73/0x2d0 May 11 10:59:48 [kernel] [ 2494.166280] [] sys_ioctl+0x4a/0x80 May 11 10:59:48 [kernel] [ 2494.166286] [] system_call_after_swapgs+0x7b/0x80 May 11 10:59:48 [kernel] [ 2494.166292] Acked-by: Alan Cox Reported-by: Marcin Slusarz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 49c1a22..e94bee0 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1215,10 +1215,11 @@ int tty_check_change(struct tty_struct *tty) if (!tty->pgrp) { printk(KERN_WARNING "tty_check_change: tty->pgrp == NULL!\n"); - goto out; + goto out_unlock; } if (task_pgrp(current) == tty->pgrp) - goto out; + goto out_unlock; + spin_unlock_irqrestore(&tty->ctrl_lock, flags); if (is_ignored(SIGTTOU)) goto out; if (is_current_pgrp_orphaned()) { @@ -1229,6 +1230,8 @@ int tty_check_change(struct tty_struct *tty) set_thread_flag(TIF_SIGPENDING); ret = -ERESTARTSYS; out: + return ret; +out_unlock: spin_unlock_irqrestore(&tty->ctrl_lock, flags); return ret; } -- cgit v1.1 From f7fd63c0b5e170efc20e7b9a0aad7f69dff62c64 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 14 May 2008 16:05:59 -0700 Subject: net/irda/irnet/irnet_irda.c needs unaligned.h net/irda/irnet/irnet_irda.c: In function 'irnet_discovery_indication': net/irda/irnet/irnet_irda.c:1676: error: implicit declaration of function 'get_unaligned' Signed-off-by: Andrew Morton Acked-by: David S. Miller Signed-off-by: Linus Torvalds --- net/irda/irnet/irnet_irda.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/irda/irnet/irnet_irda.c b/net/irda/irnet/irnet_irda.c index a3ec002..cf9a4b5 100644 --- a/net/irda/irnet/irnet_irda.c +++ b/net/irda/irnet/irnet_irda.c @@ -10,6 +10,7 @@ #include "irnet_irda.h" /* Private header */ #include +#include /* * PPP disconnect work: we need to make sure we're in -- cgit v1.1 From 08fcf1d61193d7b7779aa6d7388535e26e064a0b Mon Sep 17 00:00:00 2001 From: Luke Browning Date: Mon, 12 May 2008 14:36:59 +0000 Subject: [POWERPC] spufs: Fix pointer reference in find_victim If victim (not ctx) is in spu_run, add victim to rq. Signed-off-by: Luke Browning Acked-by: Christoph Hellwig Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/cell/spufs/sched.c b/arch/powerpc/platforms/cell/spufs/sched.c index 2e411f2..745dd51 100644 --- a/arch/powerpc/platforms/cell/spufs/sched.c +++ b/arch/powerpc/platforms/cell/spufs/sched.c @@ -659,7 +659,7 @@ static struct spu *find_victim(struct spu_context *ctx) victim->stats.invol_ctx_switch++; spu->stats.invol_ctx_switch++; - if (test_bit(SPU_SCHED_SPU_RUN, &ctx->sched_flags)) + if (test_bit(SPU_SCHED_SPU_RUN, &victim->sched_flags)) spu_add_to_rq(victim); mutex_unlock(&victim->state_mutex); -- cgit v1.1 From cec08e7a948326b01555be6311480aa08e637de2 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 30 Apr 2008 15:41:48 +1000 Subject: [POWERPC] vmemmap fixes to use smaller pages This changes vmemmap to use a different region (region 0xf) of the address space, and to configure the page size of that region dynamically at boot. The problem with the current approach of always using 16M pages is that it's not well suited to machines that have small amounts of memory such as small partitions on pseries, or PS3's. In fact, on the PS3, failure to allocate the 16M page backing vmmemmap tends to prevent hotplugging the HV's "additional" memory, thus limiting the available memory even more, from my experience down to something like 80M total, which makes it really not very useable. The logic used by my match to choose the vmemmap page size is: - If 16M pages are available and there's 1G or more RAM at boot, use that size. - Else if 64K pages are available, use that - Else use 4K pages I've tested on a POWER6 (16M pages) and on an iSeries POWER3 (4K pages) and it seems to work fine. Note that I intend to change the way we organize the kernel regions & SLBs so the actual region will change from 0xf back to something else at one point, as I simplify the SLB miss handler, but that will be for a later patch. Signed-off-by: Paul Mackerras --- arch/powerpc/mm/hash_utils_64.c | 28 ++++++++++++++++++++++++++-- arch/powerpc/mm/init_64.c | 10 ++++++---- arch/powerpc/mm/slb.c | 16 ++++++++++++++-- arch/powerpc/mm/slb_low.S | 16 +++++++++++++--- include/asm-powerpc/mmu-hash64.h | 1 + include/asm-powerpc/pgtable-ppc64.h | 10 +++++----- 6 files changed, 65 insertions(+), 16 deletions(-) diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c index 2b5a399..0f2d239 100644 --- a/arch/powerpc/mm/hash_utils_64.c +++ b/arch/powerpc/mm/hash_utils_64.c @@ -94,6 +94,9 @@ unsigned long htab_hash_mask; int mmu_linear_psize = MMU_PAGE_4K; int mmu_virtual_psize = MMU_PAGE_4K; int mmu_vmalloc_psize = MMU_PAGE_4K; +#ifdef CONFIG_SPARSEMEM_VMEMMAP +int mmu_vmemmap_psize = MMU_PAGE_4K; +#endif int mmu_io_psize = MMU_PAGE_4K; int mmu_kernel_ssize = MMU_SEGSIZE_256M; int mmu_highuser_ssize = MMU_SEGSIZE_256M; @@ -387,11 +390,32 @@ static void __init htab_init_page_sizes(void) } #endif /* CONFIG_PPC_64K_PAGES */ +#ifdef CONFIG_SPARSEMEM_VMEMMAP + /* We try to use 16M pages for vmemmap if that is supported + * and we have at least 1G of RAM at boot + */ + if (mmu_psize_defs[MMU_PAGE_16M].shift && + lmb_phys_mem_size() >= 0x40000000) + mmu_vmemmap_psize = MMU_PAGE_16M; + else if (mmu_psize_defs[MMU_PAGE_64K].shift) + mmu_vmemmap_psize = MMU_PAGE_64K; + else + mmu_vmemmap_psize = MMU_PAGE_4K; +#endif /* CONFIG_SPARSEMEM_VMEMMAP */ + printk(KERN_DEBUG "Page orders: linear mapping = %d, " - "virtual = %d, io = %d\n", + "virtual = %d, io = %d" +#ifdef CONFIG_SPARSEMEM_VMEMMAP + ", vmemmap = %d" +#endif + "\n", mmu_psize_defs[mmu_linear_psize].shift, mmu_psize_defs[mmu_virtual_psize].shift, - mmu_psize_defs[mmu_io_psize].shift); + mmu_psize_defs[mmu_io_psize].shift +#ifdef CONFIG_SPARSEMEM_VMEMMAP + ,mmu_psize_defs[mmu_vmemmap_psize].shift +#endif + ); #ifdef CONFIG_HUGETLB_PAGE /* Init large page size. Currently, we pick 16M or 1M depending diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c index c5ac532..6aa6537 100644 --- a/arch/powerpc/mm/init_64.c +++ b/arch/powerpc/mm/init_64.c @@ -19,6 +19,8 @@ * */ +#undef DEBUG + #include #include #include @@ -208,12 +210,12 @@ int __meminit vmemmap_populated(unsigned long start, int page_size) } int __meminit vmemmap_populate(struct page *start_page, - unsigned long nr_pages, int node) + unsigned long nr_pages, int node) { unsigned long mode_rw; unsigned long start = (unsigned long)start_page; unsigned long end = (unsigned long)(start_page + nr_pages); - unsigned long page_size = 1 << mmu_psize_defs[mmu_linear_psize].shift; + unsigned long page_size = 1 << mmu_psize_defs[mmu_vmemmap_psize].shift; mode_rw = _PAGE_ACCESSED | _PAGE_DIRTY | _PAGE_COHERENT | PP_RWXX; @@ -235,11 +237,11 @@ int __meminit vmemmap_populate(struct page *start_page, start, p, __pa(p)); mapped = htab_bolt_mapping(start, start + page_size, - __pa(p), mode_rw, mmu_linear_psize, + __pa(p), mode_rw, mmu_vmemmap_psize, mmu_kernel_ssize); BUG_ON(mapped < 0); } return 0; } -#endif +#endif /* CONFIG_SPARSEMEM_VMEMMAP */ diff --git a/arch/powerpc/mm/slb.c b/arch/powerpc/mm/slb.c index cf8705e..89497fb 100644 --- a/arch/powerpc/mm/slb.c +++ b/arch/powerpc/mm/slb.c @@ -28,7 +28,7 @@ #include #ifdef DEBUG -#define DBG(fmt...) udbg_printf(fmt) +#define DBG(fmt...) printk(fmt) #else #define DBG pr_debug #endif @@ -263,13 +263,19 @@ void slb_initialize(void) extern unsigned int *slb_miss_kernel_load_linear; extern unsigned int *slb_miss_kernel_load_io; extern unsigned int *slb_compare_rr_to_size; +#ifdef CONFIG_SPARSEMEM_VMEMMAP + extern unsigned int *slb_miss_kernel_load_vmemmap; + unsigned long vmemmap_llp; +#endif /* Prepare our SLB miss handler based on our page size */ linear_llp = mmu_psize_defs[mmu_linear_psize].sllp; io_llp = mmu_psize_defs[mmu_io_psize].sllp; vmalloc_llp = mmu_psize_defs[mmu_vmalloc_psize].sllp; get_paca()->vmalloc_sllp = SLB_VSID_KERNEL | vmalloc_llp; - +#ifdef CONFIG_SPARSEMEM_VMEMMAP + vmemmap_llp = mmu_psize_defs[mmu_vmemmap_psize].sllp; +#endif if (!slb_encoding_inited) { slb_encoding_inited = 1; patch_slb_encoding(slb_miss_kernel_load_linear, @@ -281,6 +287,12 @@ void slb_initialize(void) DBG("SLB: linear LLP = %04lx\n", linear_llp); DBG("SLB: io LLP = %04lx\n", io_llp); + +#ifdef CONFIG_SPARSEMEM_VMEMMAP + patch_slb_encoding(slb_miss_kernel_load_vmemmap, + SLB_VSID_KERNEL | vmemmap_llp); + DBG("SLB: vmemmap LLP = %04lx\n", vmemmap_llp); +#endif } get_paca()->stab_rr = SLB_NUM_BOLTED; diff --git a/arch/powerpc/mm/slb_low.S b/arch/powerpc/mm/slb_low.S index 657f6b3..bc44dc4 100644 --- a/arch/powerpc/mm/slb_low.S +++ b/arch/powerpc/mm/slb_low.S @@ -47,8 +47,7 @@ _GLOBAL(slb_allocate_realmode) * it to VSID 0, which is reserved as a bad VSID - one which * will never have any pages in it. */ - /* Check if hitting the linear mapping of the vmalloc/ioremap - * kernel space + /* Check if hitting the linear mapping or some other kernel space */ bne cr7,1f @@ -62,7 +61,18 @@ BEGIN_FTR_SECTION END_FTR_SECTION_IFCLR(CPU_FTR_1T_SEGMENT) b slb_finish_load_1T -1: /* vmalloc/ioremap mapping encoding bits, the "li" instructions below +1: +#ifdef CONFIG_SPARSEMEM_VMEMMAP + /* Check virtual memmap region. To be patches at kernel boot */ + cmpldi cr0,r9,0xf + bne 1f +_GLOBAL(slb_miss_kernel_load_vmemmap) + li r11,0 + b 6f +1: +#endif /* CONFIG_SPARSEMEM_VMEMMAP */ + + /* vmalloc/ioremap mapping encoding bits, the "li" instructions below * will be patched by the kernel at boot */ BEGIN_FTR_SECTION diff --git a/include/asm-powerpc/mmu-hash64.h b/include/asm-powerpc/mmu-hash64.h index 0dff767..39c5c5f 100644 --- a/include/asm-powerpc/mmu-hash64.h +++ b/include/asm-powerpc/mmu-hash64.h @@ -177,6 +177,7 @@ extern struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; extern int mmu_linear_psize; extern int mmu_virtual_psize; extern int mmu_vmalloc_psize; +extern int mmu_vmemmap_psize; extern int mmu_io_psize; extern int mmu_kernel_ssize; extern int mmu_highuser_ssize; diff --git a/include/asm-powerpc/pgtable-ppc64.h b/include/asm-powerpc/pgtable-ppc64.h index 27f1869..cc6a43b 100644 --- a/include/asm-powerpc/pgtable-ppc64.h +++ b/include/asm-powerpc/pgtable-ppc64.h @@ -65,15 +65,15 @@ #define VMALLOC_REGION_ID (REGION_ID(VMALLOC_START)) #define KERNEL_REGION_ID (REGION_ID(PAGE_OFFSET)) +#define VMEMMAP_REGION_ID (0xfUL) #define USER_REGION_ID (0UL) /* - * Defines the address of the vmemap area, in the top 16th of the - * kernel region. + * Defines the address of the vmemap area, in its own region */ -#define VMEMMAP_BASE (ASM_CONST(CONFIG_KERNEL_START) + \ - (0xfUL << (REGION_SHIFT - 4))) -#define vmemmap ((struct page *)VMEMMAP_BASE) +#define VMEMMAP_BASE (VMEMMAP_REGION_ID << REGION_SHIFT) +#define vmemmap ((struct page *)VMEMMAP_BASE) + /* * Common bits in a linux-style PTE. These match the bits in the -- cgit v1.1 From 64e4566f6d590fbb284da061b9b664c2486dd2de Mon Sep 17 00:00:00 2001 From: Timur Tabi Date: Thu, 8 May 2008 05:19:59 +1000 Subject: [POWERPC] Add null pointer check to of_find_property Update function of_find_property() to return NULL if the device_node passed to it is also NULL. Otherwise, passing NULL will cause a null pointer dereference. Without this, the legacy_serial driver will crash if there's no 'chosen' node in the device tree. Signed-off-by: Timur Tabi Signed-off-by: Paul Mackerras --- drivers/of/base.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/of/base.c b/drivers/of/base.c index 9bd7c4a..23ffb7c 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -65,6 +65,9 @@ struct property *of_find_property(const struct device_node *np, { struct property *pp; + if (!np) + return NULL; + read_lock(&devtree_lock); for (pp = np->properties; pp != 0; pp = pp->next) { if (of_prop_cmp(pp->name, name) == 0) { -- cgit v1.1 From 9c8387afdc93f90bf0241411d44e011d8d5b76df Mon Sep 17 00:00:00 2001 From: Nate Case Date: Tue, 13 May 2008 06:14:14 +1000 Subject: [POWERPC] Fix uninitialized variable bug in copy_{to|from}_user Calls to copy_to_user() or copy_from_user() can fail when copying N bytes, where N is a constant less than 8, but not 1, 2, 4, or 8, because 'ret' is not initialized and is only set if the size is 1, 2, 4 or 8, but is tested after the switch statement for any constant size <= 8. This fixes it by initializing 'ret' to 1, causing the code to fall through to the __copy_tofrom_user call for sizes other than 1, 2, 4 or 8. Signed-off-by: Dave Scidmore Signed-off-by: Nate Case Signed-off-by: Paul Mackerras --- include/asm-powerpc/uaccess.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/asm-powerpc/uaccess.h b/include/asm-powerpc/uaccess.h index 8e798e3..1a0736f 100644 --- a/include/asm-powerpc/uaccess.h +++ b/include/asm-powerpc/uaccess.h @@ -380,7 +380,7 @@ static inline unsigned long __copy_from_user_inatomic(void *to, const void __user *from, unsigned long n) { if (__builtin_constant_p(n) && (n <= 8)) { - unsigned long ret; + unsigned long ret = 1; switch (n) { case 1: @@ -406,7 +406,7 @@ static inline unsigned long __copy_to_user_inatomic(void __user *to, const void *from, unsigned long n) { if (__builtin_constant_p(n) && (n <= 8)) { - unsigned long ret; + unsigned long ret = 1; switch (n) { case 1: -- cgit v1.1 From dfe1e09f220b73ff9b5614185ef24de4c07c578d Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Tue, 13 May 2008 19:07:42 +1000 Subject: [POWERPC] spufs: Fix compile error With CONFIG_VIRT_CPU_ACCOUNTING disabled, I got the following error: linux-2.6/arch/powerpc/platforms/cell/spufs/file.c: In function 'spu_switch_log_notify': linux-2.6/arch/powerpc/platforms/cell/spufs/file.c:2542: error: implicit declaration of function 'get_tb' make[4]: *** [arch/powerpc/platforms/cell/spufs/file.o] Error 1 Signed-off-by: FUJITA Tomonori Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/spufs/file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c index 80911a3..c81341f 100644 --- a/arch/powerpc/platforms/cell/spufs/file.c +++ b/arch/powerpc/platforms/cell/spufs/file.c @@ -32,6 +32,7 @@ #include #include +#include #include #include #include -- cgit v1.1 From 7012255aaee28203c15761f864e34b806b71dd53 Mon Sep 17 00:00:00 2001 From: Ishizaki Kou Date: Wed, 14 May 2008 19:05:19 +1000 Subject: [POWERPC] cell: Fix section mismatches in io-workarounds code Fix following warnings: WARNING: arch/powerpc/platforms/cell/built-in.o(.devinit.text+0x9c): Section mismatch in reference from the function .cell_setup_phb() to the function .init.text:.iowa_register_bus() WARNING: arch/powerpc/platforms/cell/built-in.o(.devinit.text+0xa4): Section mismatch in reference from the function .cell_setup_phb() to the function .init.text:.io_workaround_init() Signed-off-by: Kou Ishizaki Signed-off-by: Paul Mackerras --- arch/powerpc/platforms/cell/io-workarounds.c | 6 +++--- arch/powerpc/platforms/cell/io-workarounds.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/powerpc/platforms/cell/io-workarounds.c b/arch/powerpc/platforms/cell/io-workarounds.c index 3b84e8b..b5f84e8 100644 --- a/arch/powerpc/platforms/cell/io-workarounds.c +++ b/arch/powerpc/platforms/cell/io-workarounds.c @@ -118,7 +118,7 @@ static void iowa_##name at \ #undef DEF_PCI_AC_RET #undef DEF_PCI_AC_NORET -static struct ppc_pci_io __initdata iowa_pci_io = { +static const struct ppc_pci_io __devinitconst iowa_pci_io = { #define DEF_PCI_AC_RET(name, ret, at, al, space, aa) .name = iowa_##name, #define DEF_PCI_AC_NORET(name, at, al, space, aa) .name = iowa_##name, @@ -146,7 +146,7 @@ static void __iomem *iowa_ioremap(unsigned long addr, unsigned long size, } /* Regist new bus to support workaround */ -void __init iowa_register_bus(struct pci_controller *phb, +void __devinit iowa_register_bus(struct pci_controller *phb, struct ppc_pci_io *ops, int (*initfunc)(struct iowa_bus *, void *), void *data) { @@ -173,7 +173,7 @@ void __init iowa_register_bus(struct pci_controller *phb, } /* enable IO workaround */ -void __init io_workaround_init(void) +void __devinit io_workaround_init(void) { static int io_workaround_inited; diff --git a/arch/powerpc/platforms/cell/io-workarounds.h b/arch/powerpc/platforms/cell/io-workarounds.h index 79d8ed3..6efc778 100644 --- a/arch/powerpc/platforms/cell/io-workarounds.h +++ b/arch/powerpc/platforms/cell/io-workarounds.h @@ -31,9 +31,9 @@ struct iowa_bus { void *private; }; -void __init io_workaround_init(void); -void __init iowa_register_bus(struct pci_controller *, struct ppc_pci_io *, - int (*)(struct iowa_bus *, void *), void *); +void __devinit io_workaround_init(void); +void __devinit iowa_register_bus(struct pci_controller *, struct ppc_pci_io *, + int (*)(struct iowa_bus *, void *), void *); struct iowa_bus *iowa_mem_find_bus(const PCI_IO_ADDR); struct iowa_bus *iowa_pio_find_bus(unsigned long); -- cgit v1.1 From faa5b9daa8bd8a18b5b1f3a8dd79261503f7cdd3 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Thu, 15 May 2008 09:12:53 +1000 Subject: [POWERPC] macintosh: Replace deprecated __initcall with device_initcall Signed-off-by: Robert P. J. Day Acked-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Paul Mackerras --- drivers/macintosh/adb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index b8b9e44..dbaad39 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -334,7 +334,7 @@ int __init adb_init(void) return 0; } -__initcall(adb_init); +device_initcall(adb_init); static int do_adb_reset_bus(void) -- cgit v1.1 From bd3bb8c15b9a80dbddfb7905b237a4a11a4725b4 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Fri, 2 May 2008 22:02:48 +0200 Subject: parisc: fix trivial section name warnings This trivial patch fixes the following section warnings on PARISC: > WARNING: vmlinux.o (.text.1): unexpected section name. >The (.[number]+) following section name are ld generated and not expected. > Did you forget to use "ax"/"aw" in a .S file? > Note that for example contains > section definitions for use in .S files. Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- arch/parisc/hpux/gate.S | 3 ++- arch/parisc/hpux/wrappers.S | 3 ++- arch/parisc/kernel/entry.S | 3 ++- arch/parisc/kernel/head.S | 2 +- arch/parisc/kernel/hpmc.S | 3 ++- arch/parisc/kernel/pacache.S | 3 ++- arch/parisc/kernel/perf_asm.S | 2 +- arch/parisc/kernel/real2.S | 13 +++++++------ arch/parisc/kernel/syscall.S | 5 +++-- arch/parisc/lib/fixup.S | 3 ++- arch/parisc/lib/lusercopy.S | 5 +++-- 11 files changed, 27 insertions(+), 18 deletions(-) diff --git a/arch/parisc/hpux/gate.S b/arch/parisc/hpux/gate.S index 38a1c1b..f0b18ce 100644 --- a/arch/parisc/hpux/gate.S +++ b/arch/parisc/hpux/gate.S @@ -13,9 +13,10 @@ #include #include #include +#include .level LEVEL - .text + __HEAD .import hpux_call_table .import hpux_syscall_exit,code diff --git a/arch/parisc/hpux/wrappers.S b/arch/parisc/hpux/wrappers.S index 58c53c8..ccd3a50 100644 --- a/arch/parisc/hpux/wrappers.S +++ b/arch/parisc/hpux/wrappers.S @@ -28,9 +28,10 @@ #include #include #include +#include .level LEVEL - .text + __HEAD /* These should probably go in a header file somewhere. * They are duplicated in kernel/wrappers.S diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 111d472..1a3935e 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -38,6 +38,7 @@ #include #include +#include #ifdef CONFIG_64BIT #define CMPIB cmpib,* @@ -629,7 +630,7 @@ * the static part of the kernel address space. */ - .text + __HEAD .align PAGE_SIZE diff --git a/arch/parisc/kernel/head.S b/arch/parisc/kernel/head.S index ec2482dc..5680a2c 100644 --- a/arch/parisc/kernel/head.S +++ b/arch/parisc/kernel/head.S @@ -32,7 +32,7 @@ ENTRY(boot_args) .word 0 /* arg3 */ END(boot_args) - .section .text.head + __HEAD .align 4 .import init_thread_union,data .import fault_vector_20,code /* IVA parisc 2.0 32 bit */ diff --git a/arch/parisc/kernel/hpmc.S b/arch/parisc/kernel/hpmc.S index 2cbf13b..068322e 100644 --- a/arch/parisc/kernel/hpmc.S +++ b/arch/parisc/kernel/hpmc.S @@ -47,6 +47,7 @@ #include #include +#include /* * stack for os_hpmc, the HPMC handler. @@ -76,7 +77,7 @@ ENTRY(hpmc_pim_data) .block HPMC_PIM_DATA_SIZE END(hpmc_pim_data) - .text + __HEAD .import intr_save, code ENTRY(os_hpmc) diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index 5901092..7e4a339 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S @@ -37,8 +37,9 @@ #include #include #include +#include - .text + __HEAD .align 128 ENTRY(flush_tlb_all_local) diff --git a/arch/parisc/kernel/perf_asm.S b/arch/parisc/kernel/perf_asm.S index 43874ca..b2a9d05 100644 --- a/arch/parisc/kernel/perf_asm.S +++ b/arch/parisc/kernel/perf_asm.S @@ -41,7 +41,7 @@ ; The coprocessor only needs to be enabled when ; starting/stopping the coprocessor with the pmenb/pmdis. ; - .text + __HEAD ENTRY(perf_intrigue_enable_perf_counters) .proc diff --git a/arch/parisc/kernel/real2.S b/arch/parisc/kernel/real2.S index 7a92695..47fbdae 100644 --- a/arch/parisc/kernel/real2.S +++ b/arch/parisc/kernel/real2.S @@ -12,6 +12,7 @@ #include #include +#include .section .bss .export real_stack @@ -39,7 +40,7 @@ save_cr_end: /************************ 32-bit real-mode calls ***********************/ /* This can be called in both narrow and wide kernels */ - .text + __HEAD /* unsigned long real32_call_asm(unsigned int *sp, * unsigned int *arg0p, @@ -113,7 +114,7 @@ ENDPROC(real32_call_asm) # define PUSH_CR(r, where) mfctl r, %r1 ! STREG,ma %r1, REG_SZ(where) # define POP_CR(r, where) LDREG,mb -REG_SZ(where), %r1 ! mtctl %r1, r - .text + __HEAD save_control_regs: load32 PA(save_cr_space), %r28 PUSH_CR(%cr24, %r28) @@ -145,7 +146,7 @@ restore_control_regs: /* rfi_virt2real() and rfi_real2virt() could perhaps be adapted for * more general-purpose use by the several places which need RFIs */ - .text + __HEAD .align 128 rfi_virt2real: /* switch to real mode... */ @@ -180,7 +181,7 @@ rfi_v2r_1: bv 0(%r2) nop - .text + __HEAD .align 128 rfi_real2virt: rsm PSW_SM_I,%r0 @@ -218,7 +219,7 @@ rfi_r2v_1: /************************ 64-bit real-mode calls ***********************/ /* This is only usable in wide kernels right now and will probably stay so */ - .text + __HEAD /* unsigned long real64_call_asm(unsigned long *sp, * unsigned long *arg0p, * unsigned long fn) @@ -276,7 +277,7 @@ ENDPROC(real64_call_asm) #endif - .text + __HEAD /* http://lists.parisc-linux.org/hypermail/parisc-linux/10916.html ** GCC 3.3 and later has a new function in libgcc.a for ** comparing function pointers. diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 69b6eeb..ae509d8 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -17,6 +17,7 @@ #include #include +#include /* We fill the empty parts of the gateway page with * something that will kill the kernel or a @@ -26,7 +27,7 @@ .level LEVEL - .text + __HEAD .import syscall_exit,code .import syscall_exit_rfi,code @@ -636,7 +637,7 @@ END(sys_call_table64) All light-weight-syscall atomic operations will use this set of locks */ - .section .data + .section .data, "aw" .align PAGE_SIZE ENTRY(lws_lock_start) /* lws locks */ diff --git a/arch/parisc/lib/fixup.S b/arch/parisc/lib/fixup.S index d172d42..4821ad6 100644 --- a/arch/parisc/lib/fixup.S +++ b/arch/parisc/lib/fixup.S @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef CONFIG_SMP .macro get_fault_ip t1 t2 @@ -55,7 +56,7 @@ .level LEVEL - .text + __HEAD .section .fixup, "ax" /* get_user() fixups, store -EFAULT in r8, and 0 in r9 */ diff --git a/arch/parisc/lib/lusercopy.S b/arch/parisc/lib/lusercopy.S index 1bd23cc..b0d8853 100644 --- a/arch/parisc/lib/lusercopy.S +++ b/arch/parisc/lib/lusercopy.S @@ -33,11 +33,12 @@ */ - .text - #include #include #include +#include + + __HEAD /* * get_sr gets the appropriate space value into -- cgit v1.1 From 9e491e54f0589cc26e2c096664e9d95493b1af29 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 14 May 2008 16:21:54 -0700 Subject: parisc: new termios definitions Signed-off-by: Alan Cox Cc: Kyle McMartin Cc: Grant Grundler Cc: Matthew Wilcox Signed-off-by: Andrew Morton Signed-off-by: Kyle McMartin --- include/asm-parisc/ioctls.h | 4 ++++ include/asm-parisc/termbits.h | 5 ++++- include/asm-parisc/termios.h | 6 ++++-- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/asm-parisc/ioctls.h b/include/asm-parisc/ioctls.h index ee84e41..6747fad 100644 --- a/include/asm-parisc/ioctls.h +++ b/include/asm-parisc/ioctls.h @@ -46,6 +46,10 @@ #define TIOCSBRK 0x5427 /* BSD compatibility */ #define TIOCCBRK 0x5428 /* BSD compatibility */ #define TIOCGSID _IOR('T', 20, int) /* Return the session ID of FD */ +#define TCGETS2 _IOR('T',0x2A, struct termios2) +#define TCSETS2 _IOW('T',0x2B, struct termios2) +#define TCSETSW2 _IOW('T',0x2C, struct termios2) +#define TCSETSF2 _IOW('T',0x2D, struct termios2) #define TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */ #define TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */ diff --git a/include/asm-parisc/termbits.h b/include/asm-parisc/termbits.h index e847fe9..d8bbc73 100644 --- a/include/asm-parisc/termbits.h +++ b/include/asm-parisc/termbits.h @@ -141,6 +141,7 @@ struct ktermios { #define HUPCL 0002000 #define CLOCAL 0004000 #define CBAUDEX 0010000 +#define BOTHER 0010000 #define B57600 0010001 #define B115200 0010002 #define B230400 0010003 @@ -156,10 +157,12 @@ struct ktermios { #define B3000000 0010015 #define B3500000 0010016 #define B4000000 0010017 -#define CIBAUD 002003600000 /* input baud rate (not used) */ +#define CIBAUD 002003600000 /* input baud rate */ #define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ +#define IBSHIFT 16 /* Shift from CBAUD to CIBAUD */ + /* c_lflag bits */ #define ISIG 0000001 diff --git a/include/asm-parisc/termios.h b/include/asm-parisc/termios.h index 5345b34..a2a57a4 100644 --- a/include/asm-parisc/termios.h +++ b/include/asm-parisc/termios.h @@ -80,8 +80,10 @@ struct termio { copy_to_user((termio)->c_cc, (termios)->c_cc, NCC); \ }) -#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios)) -#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios)) +#define user_termios_to_kernel_termios(k, u) copy_from_user(k, u, sizeof(struct termios2)) +#define kernel_termios_to_user_termios(u, k) copy_to_user(u, k, sizeof(struct termios2)) +#define user_termios_to_kernel_termios_1(k, u) copy_from_user(k, u, sizeof(struct termios)) +#define kernel_termios_to_user_termios_1(u, k) copy_to_user(u, k, sizeof(struct termios)) #endif /* __KERNEL__ */ -- cgit v1.1 From 91bae23ce185b74c9b6dda86b92bb204a1c951c3 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 14 May 2008 16:21:55 -0700 Subject: parisc: replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Cc: Kyle McMartin Cc: Matthew Wilcox Cc: Grant Grundler Signed-off-by: Andrew Morton Signed-off-by: Kyle McMartin --- arch/parisc/kernel/inventory.c | 2 +- arch/parisc/kernel/traps.c | 2 +- arch/parisc/kernel/unaligned.c | 2 +- arch/parisc/lib/memcpy.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c index 4845a64..bd1f7f1 100644 --- a/arch/parisc/kernel/inventory.c +++ b/arch/parisc/kernel/inventory.c @@ -499,7 +499,7 @@ add_system_map_addresses(struct parisc_device *dev, int num_addrs, dev->addr = kmalloc(num_addrs * sizeof(unsigned long), GFP_KERNEL); if(!dev->addr) { printk(KERN_ERR "%s %s(): memory allocation failure\n", - __FILE__, __FUNCTION__); + __FILE__, __func__); return; } diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c index 9dc6dc4..675f1d0 100644 --- a/arch/parisc/kernel/traps.c +++ b/arch/parisc/kernel/traps.c @@ -275,7 +275,7 @@ KERN_CRIT " || ||\n"); /* Wot's wrong wif bein' racy? */ if (current->thread.flags & PARISC_KERNEL_DEATH) { - printk(KERN_CRIT "%s() recursion detected.\n", __FUNCTION__); + printk(KERN_CRIT "%s() recursion detected.\n", __func__); local_irq_enable(); while (1); } diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c index aebf3c1..9f5f01e 100644 --- a/arch/parisc/kernel/unaligned.c +++ b/arch/parisc/kernel/unaligned.c @@ -30,7 +30,7 @@ /* #define DEBUG_UNALIGNED 1 */ #ifdef DEBUG_UNALIGNED -#define DPRINTF(fmt, args...) do { printk(KERN_DEBUG "%s:%d:%s ", __FILE__, __LINE__, __FUNCTION__ ); printk(KERN_DEBUG fmt, ##args ); } while (0) +#define DPRINTF(fmt, args...) do { printk(KERN_DEBUG "%s:%d:%s ", __FILE__, __LINE__, __func__ ); printk(KERN_DEBUG fmt, ##args ); } while (0) #else #define DPRINTF(fmt, args...) #endif diff --git a/arch/parisc/lib/memcpy.c b/arch/parisc/lib/memcpy.c index d22042d..2d68431 100644 --- a/arch/parisc/lib/memcpy.c +++ b/arch/parisc/lib/memcpy.c @@ -91,7 +91,7 @@ DECLARE_PER_CPU(struct exception_data, exception_data); #define THRESHOLD 16 #ifdef DEBUG_MEMCPY -#define DPRINTF(fmt, args...) do { printk(KERN_DEBUG "%s:%d:%s ", __FILE__, __LINE__, __FUNCTION__ ); printk(KERN_DEBUG fmt, ##args ); } while (0) +#define DPRINTF(fmt, args...) do { printk(KERN_DEBUG "%s:%d:%s ", __FILE__, __LINE__, __func__ ); printk(KERN_DEBUG fmt, ##args ); } while (0) #else #define DPRINTF(fmt, args...) #endif -- cgit v1.1 From a8043ecb17bd2e4b034006bee315efeea3936278 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 14 May 2008 16:21:56 -0700 Subject: drivers/parisc: replace remaining __FUNCTION__ occurrences __FUNCTION__ is gcc-specific, use __func__ Signed-off-by: Harvey Harrison Cc: Kyle McMartin Cc: Matthew Wilcox Cc: Grant Grundler Signed-off-by: Andrew Morton Signed-off-by: Kyle McMartin --- drivers/parisc/asp.c | 2 +- drivers/parisc/ccio-dma.c | 36 ++++++++++++++++++------------------ drivers/parisc/dino.c | 14 +++++++------- drivers/parisc/gsc.c | 4 ++-- drivers/parisc/lasi.c | 2 +- drivers/parisc/lba_pci.c | 22 +++++++++++----------- drivers/parisc/led.c | 2 +- drivers/parisc/sba_iommu.c | 42 +++++++++++++++++++++--------------------- drivers/parisc/wax.c | 2 +- 9 files changed, 63 insertions(+), 63 deletions(-) diff --git a/drivers/parisc/asp.c b/drivers/parisc/asp.c index 558420b..8213691 100644 --- a/drivers/parisc/asp.c +++ b/drivers/parisc/asp.c @@ -88,7 +88,7 @@ asp_init_chip(struct parisc_device *dev) ret = -EBUSY; dev->irq = gsc_claim_irq(&gsc_irq, ASP_GSC_IRQ); if (dev->irq < 0) { - printk(KERN_ERR "%s(): cannot get GSC irq\n", __FUNCTION__); + printk(KERN_ERR "%s(): cannot get GSC irq\n", __func__); goto out; } diff --git a/drivers/parisc/ccio-dma.c b/drivers/parisc/ccio-dma.c index 07d2a8d..b30e38f 100644 --- a/drivers/parisc/ccio-dma.c +++ b/drivers/parisc/ccio-dma.c @@ -359,7 +359,7 @@ ccio_alloc_range(struct ioc *ioc, struct device *dev, size_t size) BUG_ON((pages_needed * IOVP_SIZE) > DMA_CHUNK_SIZE); DBG_RES("%s() size: %d pages_needed %d\n", - __FUNCTION__, size, pages_needed); + __func__, size, pages_needed); /* ** "seek and ye shall find"...praying never hurts either... @@ -395,16 +395,16 @@ ccio_alloc_range(struct ioc *ioc, struct device *dev, size_t size) #endif } else { panic("%s: %s() Too many pages to map. pages_needed: %u\n", - __FILE__, __FUNCTION__, pages_needed); + __FILE__, __func__, pages_needed); } panic("%s: %s() I/O MMU is out of mapping resources.\n", __FILE__, - __FUNCTION__); + __func__); resource_found: DBG_RES("%s() res_idx %d res_hint: %d\n", - __FUNCTION__, res_idx, ioc->res_hint); + __func__, res_idx, ioc->res_hint); #ifdef CCIO_SEARCH_TIME { @@ -450,7 +450,7 @@ ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped) BUG_ON(pages_mapped > BITS_PER_LONG); DBG_RES("%s(): res_idx: %d pages_mapped %d\n", - __FUNCTION__, res_idx, pages_mapped); + __func__, res_idx, pages_mapped); #ifdef CCIO_MAP_STATS ioc->used_pages -= pages_mapped; @@ -474,7 +474,7 @@ ccio_free_range(struct ioc *ioc, dma_addr_t iova, unsigned long pages_mapped) #endif } else { panic("%s:%s() Too many pages to unmap.\n", __FILE__, - __FUNCTION__); + __func__); } } @@ -775,7 +775,7 @@ ccio_map_single(struct device *dev, void *addr, size_t size, pdir_start = &(ioc->pdir_base[idx]); DBG_RUN("%s() 0x%p -> 0x%lx size: %0x%x\n", - __FUNCTION__, addr, (long)iovp | offset, size); + __func__, addr, (long)iovp | offset, size); /* If not cacheline aligned, force SAFE_DMA on the whole mess */ if((size % L1_CACHE_BYTES) || ((unsigned long)addr % L1_CACHE_BYTES)) @@ -820,7 +820,7 @@ ccio_unmap_single(struct device *dev, dma_addr_t iova, size_t size, ioc = GET_IOC(dev); DBG_RUN("%s() iovp 0x%lx/%x\n", - __FUNCTION__, (long)iova, size); + __func__, (long)iova, size); iova ^= offset; /* clear offset bits */ size += offset; @@ -922,7 +922,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents, BUG_ON(!dev); ioc = GET_IOC(dev); - DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents); + DBG_RUN_SG("%s() START %d entries\n", __func__, nents); /* Fast path single entry scatterlists. */ if (nents == 1) { @@ -966,7 +966,7 @@ ccio_map_sg(struct device *dev, struct scatterlist *sglist, int nents, BUG_ON(coalesced != filled); - DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled); + DBG_RUN_SG("%s() DONE %d mappings\n", __func__, filled); for (i = 0; i < filled; i++) current_len += sg_dma_len(sglist + i); @@ -995,7 +995,7 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, ioc = GET_IOC(dev); DBG_RUN_SG("%s() START %d entries, %08lx,%x\n", - __FUNCTION__, nents, sg_virt_addr(sglist), sglist->length); + __func__, nents, sg_virt_addr(sglist), sglist->length); #ifdef CCIO_MAP_STATS ioc->usg_calls++; @@ -1011,7 +1011,7 @@ ccio_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, ++sglist; } - DBG_RUN_SG("%s() DONE (nents %d)\n", __FUNCTION__, nents); + DBG_RUN_SG("%s() DONE (nents %d)\n", __func__, nents); } static struct hppa_dma_ops ccio_ops = { @@ -1225,7 +1225,7 @@ static int ccio_get_iotlb_size(struct parisc_device *dev) { if (dev->spa_shift == 0) { - panic("%s() : Can't determine I/O TLB size.\n", __FUNCTION__); + panic("%s() : Can't determine I/O TLB size.\n", __func__); } return (1 << dev->spa_shift); } @@ -1315,7 +1315,7 @@ ccio_ioc_init(struct ioc *ioc) BUG_ON((1 << get_order(ioc->pdir_size)) != (ioc->pdir_size >> PAGE_SHIFT)); DBG_INIT("%s() hpa 0x%p mem %luMB IOV %dMB (%d bits)\n", - __FUNCTION__, ioc->ioc_regs, + __func__, ioc->ioc_regs, (unsigned long) num_physpages >> (20 - PAGE_SHIFT), iova_space_size>>20, iov_order + PAGE_SHIFT); @@ -1323,7 +1323,7 @@ ccio_ioc_init(struct ioc *ioc) ioc->pdir_base = (u64 *)__get_free_pages(GFP_KERNEL, get_order(ioc->pdir_size)); if(NULL == ioc->pdir_base) { - panic("%s() could not allocate I/O Page Table\n", __FUNCTION__); + panic("%s() could not allocate I/O Page Table\n", __func__); } memset(ioc->pdir_base, 0, ioc->pdir_size); @@ -1332,12 +1332,12 @@ ccio_ioc_init(struct ioc *ioc) /* resource map size dictated by pdir_size */ ioc->res_size = (ioc->pdir_size / sizeof(u64)) >> 3; - DBG_INIT("%s() res_size 0x%x\n", __FUNCTION__, ioc->res_size); + DBG_INIT("%s() res_size 0x%x\n", __func__, ioc->res_size); ioc->res_map = (u8 *)__get_free_pages(GFP_KERNEL, get_order(ioc->res_size)); if(NULL == ioc->res_map) { - panic("%s() could not allocate resource map\n", __FUNCTION__); + panic("%s() could not allocate resource map\n", __func__); } memset(ioc->res_map, 0, ioc->res_size); @@ -1409,7 +1409,7 @@ ccio_init_resource(struct resource *res, char *name, void __iomem *ioaddr) result = insert_resource(&iomem_resource, res); if (result < 0) { printk(KERN_ERR "%s() failed to claim CCIO bus address space (%08lx,%08lx)\n", - __FUNCTION__, res->start, res->end); + __func__, res->start, res->end); } } diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index d9c6322..fd56128 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -180,7 +180,7 @@ static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where, void __iomem *base_addr = d->hba.base_addr; unsigned long flags; - DBG("%s: %p, %d, %d, %d\n", __FUNCTION__, base_addr, devfn, where, + DBG("%s: %p, %d, %d, %d\n", __func__, base_addr, devfn, where, size); spin_lock_irqsave(&d->dinosaur_pen, flags); @@ -215,7 +215,7 @@ static int dino_cfg_write(struct pci_bus *bus, unsigned int devfn, int where, void __iomem *base_addr = d->hba.base_addr; unsigned long flags; - DBG("%s: %p, %d, %d, %d\n", __FUNCTION__, base_addr, devfn, where, + DBG("%s: %p, %d, %d, %d\n", __func__, base_addr, devfn, where, size); spin_lock_irqsave(&d->dinosaur_pen, flags); @@ -301,7 +301,7 @@ static void dino_disable_irq(unsigned int irq) struct dino_device *dino_dev = irq_desc[irq].chip_data; int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS); - DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq); + DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, irq); /* Clear the matching bit in the IMR register */ dino_dev->imr &= ~(DINO_MASK_IRQ(local_irq)); @@ -314,7 +314,7 @@ static void dino_enable_irq(unsigned int irq) int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS); u32 tmp; - DBG(KERN_WARNING "%s(0x%p, %d)\n", __FUNCTION__, dino_dev, irq); + DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, irq); /* ** clear pending IRQ bits @@ -340,7 +340,7 @@ static void dino_enable_irq(unsigned int irq) tmp = __raw_readl(dino_dev->hba.base_addr+DINO_ILR); if (tmp & DINO_MASK_IRQ(local_irq)) { DBG(KERN_WARNING "%s(): IRQ asserted! (ILR 0x%x)\n", - __FUNCTION__, tmp); + __func__, tmp); gsc_writel(dino_dev->txn_data, dino_dev->txn_addr); } } @@ -388,7 +388,7 @@ ilr_again: int local_irq = __ffs(mask); int irq = dino_dev->global_irq[local_irq]; DBG(KERN_DEBUG "%s(%d, %p) mask 0x%x\n", - __FUNCTION__, irq, intr_dev, mask); + __func__, irq, intr_dev, mask); __do_IRQ(irq); mask &= ~(1 << local_irq); } while (mask); @@ -566,7 +566,7 @@ dino_fixup_bus(struct pci_bus *bus) int port_base = HBA_PORT_BASE(dino_dev->hba.hba_num); DBG(KERN_WARNING "%s(0x%p) bus %d platform_data 0x%p\n", - __FUNCTION__, bus, bus->secondary, + __func__, bus, bus->secondary, bus->bridge->platform_data); /* Firmware doesn't set up card-mode dino, so we have to */ diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index 1b3e3fd..f7d088b 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c @@ -112,7 +112,7 @@ static void gsc_asic_disable_irq(unsigned int irq) int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32); u32 imr; - DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __FUNCTION__, irq, + DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, irq, irq_dev->name, imr); /* Disable the IRQ line by clearing the bit in the IMR */ @@ -127,7 +127,7 @@ static void gsc_asic_enable_irq(unsigned int irq) int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32); u32 imr; - DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __FUNCTION__, irq, + DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, irq, irq_dev->name, imr); /* Enable the IRQ line by setting the bit in the IMR */ diff --git a/drivers/parisc/lasi.c b/drivers/parisc/lasi.c index cb3d281..bee5100 100644 --- a/drivers/parisc/lasi.c +++ b/drivers/parisc/lasi.c @@ -193,7 +193,7 @@ lasi_init_chip(struct parisc_device *dev) dev->irq = gsc_alloc_irq(&gsc_irq); if (dev->irq < 0) { printk(KERN_ERR "%s(): cannot get GSC irq\n", - __FUNCTION__); + __func__); kfree(lasi); return -EBUSY; } diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index 66ce610..a28c894 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -377,12 +377,12 @@ static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int /* original - Generate config cycle on broken elroy with risk we will miss PCI bus errors. */ *data = lba_rd_cfg(d, tok, pos, size); - DBG_CFG("%s(%x+%2x) -> 0x%x (a)\n", __FUNCTION__, tok, pos, *data); + DBG_CFG("%s(%x+%2x) -> 0x%x (a)\n", __func__, tok, pos, *data); return 0; } if (LBA_SKIP_PROBE(d) && !lba_device_present(bus->secondary, devfn, d)) { - DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __FUNCTION__, tok, pos); + DBG_CFG("%s(%x+%2x) -> -1 (b)\n", __func__, tok, pos); /* either don't want to look or know device isn't present. */ *data = ~0U; return(0); @@ -398,7 +398,7 @@ static int elroy_cfg_read(struct pci_bus *bus, unsigned int devfn, int pos, int case 2: *data = READ_REG16(data_reg + (pos & 2)); break; case 4: *data = READ_REG32(data_reg); break; } - DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __FUNCTION__, tok, pos, *data); + DBG_CFG("%s(%x+%2x) -> 0x%x (c)\n", __func__, tok, pos, *data); return 0; } @@ -441,16 +441,16 @@ static int elroy_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, int if (!LBA_SKIP_PROBE(d)) { /* Original Workaround */ lba_wr_cfg(d, tok, pos, (u32) data, size); - DBG_CFG("%s(%x+%2x) = 0x%x (a)\n", __FUNCTION__, tok, pos,data); + DBG_CFG("%s(%x+%2x) = 0x%x (a)\n", __func__, tok, pos,data); return 0; } if (LBA_SKIP_PROBE(d) && (!lba_device_present(bus->secondary, devfn, d))) { - DBG_CFG("%s(%x+%2x) = 0x%x (b)\n", __FUNCTION__, tok, pos,data); + DBG_CFG("%s(%x+%2x) = 0x%x (b)\n", __func__, tok, pos,data); return 1; /* New Workaround */ } - DBG_CFG("%s(%x+%2x) = 0x%x (c)\n", __FUNCTION__, tok, pos, data); + DBG_CFG("%s(%x+%2x) = 0x%x (c)\n", __func__, tok, pos, data); /* Basic Algorithm */ LBA_CFG_ADDR_SETUP(d, tok | pos); @@ -521,7 +521,7 @@ static int mercury_cfg_write(struct pci_bus *bus, unsigned int devfn, int pos, i if ((pos > 255) || (devfn > 255)) return -EINVAL; - DBG_CFG("%s(%x+%2x) <- 0x%x (c)\n", __FUNCTION__, tok, pos, data); + DBG_CFG("%s(%x+%2x) <- 0x%x (c)\n", __func__, tok, pos, data); LBA_CFG_TR4_ADDR_SETUP(d, tok | pos); switch(size) { @@ -890,7 +890,7 @@ LBA_PORT_IN(32, 0) #define LBA_PORT_OUT(size, mask) \ static void lba_astro_out##size (struct pci_hba_data *d, u16 addr, u##size val) \ { \ - DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, d, addr, val); \ + DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __func__, d, addr, val); \ WRITE_REG##size(val, astro_iop_base + addr); \ if (LBA_DEV(d)->hw_rev < 3) \ lba_t32 = READ_U32(d->base_addr + LBA_FUNC_ID); \ @@ -932,7 +932,7 @@ static struct pci_port_ops lba_astro_port_ops = { static u##size lba_pat_in##size (struct pci_hba_data *l, u16 addr) \ { \ u##size t; \ - DBG_PORT("%s(0x%p, 0x%x) ->", __FUNCTION__, l, addr); \ + DBG_PORT("%s(0x%p, 0x%x) ->", __func__, l, addr); \ t = READ_REG##size(PIOP_TO_GMMIO(LBA_DEV(l), addr)); \ DBG_PORT(" 0x%x\n", t); \ return (t); \ @@ -948,7 +948,7 @@ LBA_PORT_IN(32, 0) static void lba_pat_out##size (struct pci_hba_data *l, u16 addr, u##size val) \ { \ void __iomem *where = PIOP_TO_GMMIO(LBA_DEV(l), addr); \ - DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __FUNCTION__, l, addr, val); \ + DBG_PORT("%s(0x%p, 0x%x, 0x%x)\n", __func__, l, addr, val); \ WRITE_REG##size(val, where); \ /* flush the I/O down to the elroy at least */ \ lba_t32 = READ_U32(l->base_addr + LBA_FUNC_ID); \ @@ -1584,7 +1584,7 @@ void lba_set_iregs(struct parisc_device *lba, u32 ibase, u32 imask) WARN_ON((ibase & 0x001fffff) != 0); WARN_ON((imask & 0x001fffff) != 0); - DBG("%s() ibase 0x%x imask 0x%x\n", __FUNCTION__, ibase, imask); + DBG("%s() ibase 0x%x imask 0x%x\n", __func__, ibase, imask); WRITE_REG32( imask, base_addr + LBA_IMASK); WRITE_REG32( ibase, base_addr + LBA_IBASE); iounmap(base_addr); diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c index 703b85e..f9b1266 100644 --- a/drivers/parisc/led.c +++ b/drivers/parisc/led.c @@ -569,7 +569,7 @@ int __init register_led_driver(int model, unsigned long cmd_reg, unsigned long d default: printk(KERN_ERR "%s: Wrong LCD/LED model %d !\n", - __FUNCTION__, lcd_info.model); + __func__, lcd_info.model); return 1; } diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index afc849b..bc73b96 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -384,7 +384,7 @@ sba_search_bitmap(struct ioc *ioc, struct device *dev, } mask = RESMAP_MASK(bits_wanted) >> bitshiftcnt; - DBG_RES("%s() o %ld %p", __FUNCTION__, o, res_ptr); + DBG_RES("%s() o %ld %p", __func__, o, res_ptr); while(res_ptr < res_end) { DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr); @@ -454,7 +454,7 @@ sba_alloc_range(struct ioc *ioc, struct device *dev, size_t size) #endif DBG_RES("%s(%x) %d -> %lx hint %x/%x\n", - __FUNCTION__, size, pages_needed, pide, + __func__, size, pages_needed, pide, (uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map), ioc->res_bitshift ); @@ -497,7 +497,7 @@ sba_free_range(struct ioc *ioc, dma_addr_t iova, size_t size) unsigned long m = RESMAP_MASK(bits_not_wanted) >> (pide & (BITS_PER_LONG - 1)); DBG_RES("%s( ,%x,%x) %x/%lx %x %p %lx\n", - __FUNCTION__, (uint) iova, size, + __func__, (uint) iova, size, bits_not_wanted, m, pide, res_ptr, *res_ptr); #ifdef SBA_COLLECT_STATS @@ -740,7 +740,7 @@ sba_map_single(struct device *dev, void *addr, size_t size, iovp = (dma_addr_t) pide << IOVP_SHIFT; DBG_RUN("%s() 0x%p -> 0x%lx\n", - __FUNCTION__, addr, (long) iovp | offset); + __func__, addr, (long) iovp | offset); pdir_start = &(ioc->pdir_base[pide]); @@ -798,7 +798,7 @@ sba_unmap_single(struct device *dev, dma_addr_t iova, size_t size, unsigned long flags; dma_addr_t offset; - DBG_RUN("%s() iovp 0x%lx/%x\n", __FUNCTION__, (long) iova, size); + DBG_RUN("%s() iovp 0x%lx/%x\n", __func__, (long) iova, size); ioc = GET_IOC(dev); offset = iova & ~IOVP_MASK; @@ -937,7 +937,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, int coalesced, filled = 0; unsigned long flags; - DBG_RUN_SG("%s() START %d entries\n", __FUNCTION__, nents); + DBG_RUN_SG("%s() START %d entries\n", __func__, nents); ioc = GET_IOC(dev); @@ -998,7 +998,7 @@ sba_map_sg(struct device *dev, struct scatterlist *sglist, int nents, spin_unlock_irqrestore(&ioc->res_lock, flags); - DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled); + DBG_RUN_SG("%s() DONE %d mappings\n", __func__, filled); return filled; } @@ -1023,7 +1023,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, #endif DBG_RUN_SG("%s() START %d entries, %p,%x\n", - __FUNCTION__, nents, sg_virt_addr(sglist), sglist->length); + __func__, nents, sg_virt_addr(sglist), sglist->length); ioc = GET_IOC(dev); @@ -1047,7 +1047,7 @@ sba_unmap_sg(struct device *dev, struct scatterlist *sglist, int nents, ++sglist; } - DBG_RUN_SG("%s() DONE (nents %d)\n", __FUNCTION__, nents); + DBG_RUN_SG("%s() DONE (nents %d)\n", __func__, nents); #ifdef ASSERT_PDIR_SANITY spin_lock_irqsave(&ioc->res_lock, flags); @@ -1118,7 +1118,7 @@ sba_alloc_pdir(unsigned int pdir_size) pdir_base = __get_free_pages(GFP_KERNEL, pdir_order); if (NULL == (void *) pdir_base) { panic("%s() could not allocate I/O Page Table\n", - __FUNCTION__); + __func__); } /* If this is not PA8700 (PCX-W2) @@ -1261,7 +1261,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ioc->pdir_size = (iova_space_size / IOVP_SIZE) * sizeof(u64); DBG_INIT("%s() hpa 0x%p IOV %dMB (%d bits)\n", - __FUNCTION__, ioc->ioc_hpa, iova_space_size >> 20, + __func__, ioc->ioc_hpa, iova_space_size >> 20, iov_order + PAGE_SHIFT); ioc->pdir_base = (void *) __get_free_pages(GFP_KERNEL, @@ -1272,7 +1272,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) memset(ioc->pdir_base, 0, ioc->pdir_size); DBG_INIT("%s() pdir %p size %x\n", - __FUNCTION__, ioc->pdir_base, ioc->pdir_size); + __func__, ioc->pdir_base, ioc->pdir_size); #ifdef SBA_HINT_SUPPORT ioc->hint_shift_pdir = iov_order + PAGE_SHIFT; @@ -1354,7 +1354,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) if (agp_found && sba_reserve_agpgart) { printk(KERN_INFO "%s: reserving %dMb of IOVA space for agpgart\n", - __FUNCTION__, (iova_space_size/2) >> 20); + __func__, (iova_space_size/2) >> 20); ioc->pdir_size /= 2; ioc->pdir_base[PDIR_INDEX(iova_space_size/2)] = SBA_AGPGART_COOKIE; } @@ -1406,7 +1406,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ioc->pdir_size = pdir_size = (iova_space_size/IOVP_SIZE) * sizeof(u64); DBG_INIT("%s() hpa 0x%lx mem %ldMB IOV %dMB (%d bits)\n", - __FUNCTION__, + __func__, ioc->ioc_hpa, (unsigned long) num_physpages >> (20 - PAGE_SHIFT), iova_space_size>>20, @@ -1415,7 +1415,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ioc->pdir_base = sba_alloc_pdir(pdir_size); DBG_INIT("%s() pdir %p size %x\n", - __FUNCTION__, ioc->pdir_base, pdir_size); + __func__, ioc->pdir_base, pdir_size); #ifdef SBA_HINT_SUPPORT /* FIXME : DMA HINTs not used */ @@ -1443,7 +1443,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) #endif DBG_INIT("%s() IOV base 0x%lx mask 0x%0lx\n", - __FUNCTION__, ioc->ibase, ioc->imask); + __func__, ioc->ibase, ioc->imask); /* ** FIXME: Hint registers are programmed with default hint @@ -1470,7 +1470,7 @@ sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ioc->ibase = 0; /* used by SBA_IOVA and related macros */ - DBG_INIT("%s() DONE\n", __FUNCTION__); + DBG_INIT("%s() DONE\n", __func__); } @@ -1544,7 +1544,7 @@ printk("sba_hw_init(): mem_boot 0x%x 0x%x 0x%x 0x%x\n", PAGE0->mem_boot.hpa, if (!IS_PLUTO(sba_dev->dev)) { ioc_ctl = READ_REG(sba_dev->sba_hpa+IOC_CTRL); DBG_INIT("%s() hpa 0x%lx ioc_ctl 0x%Lx ->", - __FUNCTION__, sba_dev->sba_hpa, ioc_ctl); + __func__, sba_dev->sba_hpa, ioc_ctl); ioc_ctl &= ~(IOC_CTRL_RM | IOC_CTRL_NC | IOC_CTRL_CE); ioc_ctl |= IOC_CTRL_DD | IOC_CTRL_D4 | IOC_CTRL_TC; /* j6700 v1.6 firmware sets 0x294f */ @@ -1675,7 +1675,7 @@ sba_common_init(struct sba_device *sba_dev) res_size >>= 3; /* convert bit count to byte count */ DBG_INIT("%s() res_size 0x%x\n", - __FUNCTION__, res_size); + __func__, res_size); sba_dev->ioc[i].res_size = res_size; sba_dev->ioc[i].res_map = (char *) __get_free_pages(GFP_KERNEL, get_order(res_size)); @@ -1688,7 +1688,7 @@ sba_common_init(struct sba_device *sba_dev) if (NULL == sba_dev->ioc[i].res_map) { panic("%s:%s() could not allocate resource map\n", - __FILE__, __FUNCTION__ ); + __FILE__, __func__ ); } memset(sba_dev->ioc[i].res_map, 0, res_size); @@ -1725,7 +1725,7 @@ sba_common_init(struct sba_device *sba_dev) #endif DBG_INIT("%s() %d res_map %x %p\n", - __FUNCTION__, i, res_size, sba_dev->ioc[i].res_map); + __func__, i, res_size, sba_dev->ioc[i].res_map); } spin_lock_init(&sba_dev->sba_lock); diff --git a/drivers/parisc/wax.c b/drivers/parisc/wax.c index 813c2c2..892a83b 100644 --- a/drivers/parisc/wax.c +++ b/drivers/parisc/wax.c @@ -93,7 +93,7 @@ wax_init_chip(struct parisc_device *dev) dev->irq = gsc_claim_irq(&gsc_irq, WAX_GSC_IRQ); if (dev->irq < 0) { printk(KERN_ERR "%s(): cannot get GSC irq\n", - __FUNCTION__); + __func__); kfree(wax); return -EBUSY; } -- cgit v1.1 From b64af9b54c17008705367f554131415793a03fba Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Wed, 14 May 2008 16:21:56 -0700 Subject: parisc: remove redundant display of free swap space in show_mem() show_mem() has no need to print the amount of free swap space manually because show_free_areas() does this already and is called by the former. The two outputs only differ in text formatting: printk("Free swap = %lukB\n", ...); printk("Free swap: %6ldkB\n", ...); Signed-off-by: Johannes Weiner Cc: Kyle McMartin Cc: Matthew Wilcox Cc: Grant Grundler Signed-off-by: Andrew Morton Signed-off-by: Kyle McMartin --- arch/parisc/mm/init.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/parisc/mm/init.c b/arch/parisc/mm/init.c index 1f01284..4ce6055 100644 --- a/arch/parisc/mm/init.c +++ b/arch/parisc/mm/init.c @@ -555,8 +555,6 @@ void show_mem(void) printk(KERN_INFO "Mem-info:\n"); show_free_areas(); - printk(KERN_INFO "Free swap: %6ldkB\n", - nr_swap_pages<<(PAGE_SHIFT-10)); #ifndef CONFIG_DISCONTIGMEM i = max_mapnr; while (i-- > 0) { -- cgit v1.1 From e557d2775a530c12818fcb5895c4457a5fec59ae Mon Sep 17 00:00:00 2001 From: "S.Caglar Onur" Date: Wed, 14 May 2008 16:21:57 -0700 Subject: arch/parisc/kernel/unaligned.c: use time_* macros The functions time_before, time_before_eq, time_after, and time_after_eq are more robust for comparing jiffies against other values. So use the time_after() macro, defined in linux/jiffies.h, which deals with wrapping correctl [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: S.Caglar Onur Cc: Kyle McMartin Cc: Matthew Wilcox Cc: Grant Grundler Signed-off-by: Andrew Morton Signed-off-by: Kyle McMartin --- arch/parisc/kernel/unaligned.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/parisc/kernel/unaligned.c b/arch/parisc/kernel/unaligned.c index 9f5f01e..e6f4b7a 100644 --- a/arch/parisc/kernel/unaligned.c +++ b/arch/parisc/kernel/unaligned.c @@ -460,7 +460,8 @@ void handle_unaligned(struct pt_regs *regs) goto force_sigbus; } - if (unaligned_count > 5 && jiffies - last_time > 5*HZ) { + if (unaligned_count > 5 && + time_after(jiffies, last_time + 5 * HZ)) { unaligned_count = 0; last_time = jiffies; } -- cgit v1.1 From 32aff5732a11739e81994b3bcd7a9d0e8b1ea06e Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Thu, 15 May 2008 16:52:29 +0200 Subject: [S390] cio: Remove CCW_CMD_SUSPEND_RECONN in front of CCW_CMD_SET_PGID. CCW_CMD_SUSPEND_RECONN causes a system hang if the cable of a reserved DASD is disconnected and connected again. Signed-off-by: Michael Ernst Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/device_pgid.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/s390/cio/device_pgid.c b/drivers/s390/cio/device_pgid.c index ba55905..5cf7be0 100644 --- a/drivers/s390/cio/device_pgid.c +++ b/drivers/s390/cio/device_pgid.c @@ -243,16 +243,10 @@ __ccw_device_do_pgid(struct ccw_device *cdev, __u8 func) /* Setup sense path group id channel program. */ cdev->private->pgid[0].inf.fc = func; ccw = cdev->private->iccws; - if (!cdev->private->flags.pgid_single) { - cdev->private->pgid[0].inf.fc |= SPID_FUNC_MULTI_PATH; - ccw->cmd_code = CCW_CMD_SUSPEND_RECONN; - ccw->cda = 0; - ccw->count = 0; - ccw->flags = CCW_FLAG_SLI | CCW_FLAG_CC; - ccw++; - } else + if (cdev->private->flags.pgid_single) cdev->private->pgid[0].inf.fc |= SPID_FUNC_SINGLE_PATH; - + else + cdev->private->pgid[0].inf.fc |= SPID_FUNC_MULTI_PATH; ccw->cmd_code = CCW_CMD_SET_PGID; ccw->cda = (__u32) __pa (&cdev->private->pgid[0]); ccw->count = sizeof (struct pgid); -- cgit v1.1 From e0a45ee0b922b998f8d6737cf6e9e69a791252b7 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 15 May 2008 16:52:30 +0200 Subject: [S390] Remove last traces of cio_msg=. cio_msg= is gone, also remove it from kernel-parameters.txt. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- Documentation/kernel-parameters.txt | 3 --- 1 file changed, 3 deletions(-) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index cdd5b93..7038a6d 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -398,9 +398,6 @@ and is between 256 and 4096 characters. It is defined in the file cio_ignore= [S390] See Documentation/s390/CommonIO for details. - cio_msg= [S390] - See Documentation/s390/CommonIO for details. - clock= [BUGS=X86-32, HW] gettimeofday clocksource override. [Deprecated] Forces specified clocksource (if available) to be used -- cgit v1.1 From 2069e978d5a6e7b45d58027e3de7f879b8c5e488 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 15 May 2008 16:52:31 +0200 Subject: [S390] sparsemem vmemmap: initialize memmap. Let's just use the generic vmmemmap_alloc_block() function which always returns initialized memory. Cc: Gerald Schaefer Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/mm/vmem.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index beccacf..ea28048 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c @@ -27,19 +27,12 @@ struct memory_segment { static LIST_HEAD(mem_segs); -static void __ref *vmem_alloc_pages(unsigned int order) -{ - if (slab_is_available()) - return (void *)__get_free_pages(GFP_KERNEL, order); - return alloc_bootmem_pages((1 << order) * PAGE_SIZE); -} - -static inline pud_t *vmem_pud_alloc(void) +static pud_t *vmem_pud_alloc(void) { pud_t *pud = NULL; #ifdef CONFIG_64BIT - pud = vmem_alloc_pages(2); + pud = vmemmap_alloc_block(PAGE_SIZE * 4, 0); if (!pud) return NULL; clear_table((unsigned long *) pud, _REGION3_ENTRY_EMPTY, PAGE_SIZE * 4); @@ -47,12 +40,12 @@ static inline pud_t *vmem_pud_alloc(void) return pud; } -static inline pmd_t *vmem_pmd_alloc(void) +static pmd_t *vmem_pmd_alloc(void) { pmd_t *pmd = NULL; #ifdef CONFIG_64BIT - pmd = vmem_alloc_pages(2); + pmd = vmemmap_alloc_block(PAGE_SIZE * 4, 0); if (!pmd) return NULL; clear_table((unsigned long *) pmd, _SEGMENT_ENTRY_EMPTY, PAGE_SIZE * 4); @@ -60,7 +53,7 @@ static inline pmd_t *vmem_pmd_alloc(void) return pmd; } -static pte_t __init_refok *vmem_pte_alloc(void) +static pte_t __ref *vmem_pte_alloc(void) { pte_t *pte; @@ -214,7 +207,7 @@ int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) if (pte_none(*pt_dir)) { unsigned long new_page; - new_page =__pa(vmem_alloc_pages(0)); + new_page =__pa(vmemmap_alloc_block(PAGE_SIZE, 0)); if (!new_page) goto out; pte = pfn_pte(new_page >> PAGE_SHIFT, PAGE_KERNEL); -- cgit v1.1 From 3cb2cea15e707dd030b3293d6d08183da369d291 Mon Sep 17 00:00:00 2001 From: Marcin Slusarz Date: Thu, 15 May 2008 16:52:32 +0200 Subject: [S390] vmlogrdr: module initialization function should return negative errors Signed-off-by: Marcin Slusarz Signed-off-by: Martin Schwidefsky --- drivers/s390/char/vmlogrdr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index d364e0b..e848734 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c @@ -858,7 +858,7 @@ static int __init vmlogrdr_init(void) for (i=0; i < MAXMINOR; ++i ) { sys_ser[i].buffer = (char *) get_zeroed_page(GFP_KERNEL); if (!sys_ser[i].buffer) { - rc = ENOMEM; + rc = -ENOMEM; break; } sys_ser[i].current_position = sys_ser[i].buffer; -- cgit v1.1 From c7a8548ffa0a2cf6313fe8b3bb4b4a199a9a080f Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Thu, 15 May 2008 16:52:33 +0200 Subject: [S390] blacklist.c: removed duplicated include Removed duplicated include in drivers/s390/cio/blacklist.c. Signed-off-by: Huang Weiyi Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/blacklist.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/s390/cio/blacklist.c b/drivers/s390/cio/blacklist.c index 9c21b8f..a4a5f2e 100644 --- a/drivers/s390/cio/blacklist.c +++ b/drivers/s390/cio/blacklist.c @@ -19,7 +19,6 @@ #include #include -#include #include "blacklist.h" #include "cio.h" -- cgit v1.1 From 69f90f6a5650a74dd8f428e8d2f05859d58da3d7 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 15 May 2008 16:52:34 +0200 Subject: [S390] dasd: Use const in busid functions. We should use 'const char *' in the busid functions since the strings are not modified anyway. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_devmap.c | 10 +++++----- drivers/s390/block/dasd_int.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index f4fb402..d774e79 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c @@ -86,10 +86,10 @@ static DEFINE_SPINLOCK(dasd_devmap_lock); static struct list_head dasd_hashlists[256]; int dasd_max_devindex; -static struct dasd_devmap *dasd_add_busid(char *, int); +static struct dasd_devmap *dasd_add_busid(const char *, int); static inline int -dasd_hash_busid(char *bus_id) +dasd_hash_busid(const char *bus_id) { int hash, i; @@ -394,7 +394,7 @@ dasd_parse(void) * devices. */ static struct dasd_devmap * -dasd_add_busid(char *bus_id, int features) +dasd_add_busid(const char *bus_id, int features) { struct dasd_devmap *devmap, *new, *tmp; int hash; @@ -430,7 +430,7 @@ dasd_add_busid(char *bus_id, int features) * Find devmap for device with given bus_id. */ static struct dasd_devmap * -dasd_find_busid(char *bus_id) +dasd_find_busid(const char *bus_id) { struct dasd_devmap *devmap, *tmp; int hash; @@ -452,7 +452,7 @@ dasd_find_busid(char *bus_id) * Check if busid has been added to the list of dasd ranges. */ int -dasd_busid_known(char *bus_id) +dasd_busid_known(const char *bus_id) { return IS_ERR(dasd_find_busid(bus_id)) ? -ENOENT : 0; } diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 6c624bf..fb2f931 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -598,7 +598,7 @@ struct dasd_device *dasd_device_from_cdev_locked(struct ccw_device *); struct dasd_device *dasd_device_from_devindex(int); int dasd_parse(void); -int dasd_busid_known(char *); +int dasd_busid_known(const char *); /* externals in dasd_gendisk.c */ int dasd_gendisk_init(void); -- cgit v1.1 From 5cbbf16a0fab91662af8400b5ada658990932a87 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 15 May 2008 16:52:35 +0200 Subject: [S390] s390dbf: Use const char * for dbf name. We should use const char * for passing the name of the debug feature around since it will not be changed. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/debug.c | 20 ++++++++++---------- include/asm-s390/debug.h | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index dff0568..c93d129 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -71,7 +71,7 @@ static ssize_t debug_input(struct file *file, const char __user *user_buf, size_t user_len, loff_t * offset); static int debug_open(struct inode *inode, struct file *file); static int debug_close(struct inode *inode, struct file *file); -static debug_info_t* debug_info_create(char *name, int pages_per_area, +static debug_info_t *debug_info_create(const char *name, int pages_per_area, int nr_areas, int buf_size, mode_t mode); static void debug_info_get(debug_info_t *); static void debug_info_put(debug_info_t *); @@ -234,8 +234,8 @@ fail_malloc_areas: */ static debug_info_t* -debug_info_alloc(char *name, int pages_per_area, int nr_areas, int buf_size, - int level, int mode) +debug_info_alloc(const char *name, int pages_per_area, int nr_areas, + int buf_size, int level, int mode) { debug_info_t* rc; @@ -326,8 +326,8 @@ debug_info_free(debug_info_t* db_info){ */ static debug_info_t* -debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size, - mode_t mode) +debug_info_create(const char *name, int pages_per_area, int nr_areas, + int buf_size, mode_t mode) { debug_info_t* rc; @@ -684,9 +684,9 @@ debug_close(struct inode *inode, struct file *file) * - Returns handle for debug area */ -debug_info_t *debug_register_mode(char *name, int pages_per_area, int nr_areas, - int buf_size, mode_t mode, uid_t uid, - gid_t gid) +debug_info_t *debug_register_mode(const char *name, int pages_per_area, + int nr_areas, int buf_size, mode_t mode, + uid_t uid, gid_t gid) { debug_info_t *rc = NULL; @@ -722,8 +722,8 @@ EXPORT_SYMBOL(debug_register_mode); * - returns handle for debug area */ -debug_info_t *debug_register(char *name, int pages_per_area, int nr_areas, - int buf_size) +debug_info_t *debug_register(const char *name, int pages_per_area, + int nr_areas, int buf_size) { return debug_register_mode(name, pages_per_area, nr_areas, buf_size, S_IRUSR | S_IWUSR, 0, 0); diff --git a/include/asm-s390/debug.h b/include/asm-s390/debug.h index 335baf4..9450ce6 100644 --- a/include/asm-s390/debug.h +++ b/include/asm-s390/debug.h @@ -120,10 +120,10 @@ debug_entry_t* debug_exception_common(debug_info_t* id, int level, /* Debug Feature API: */ -debug_info_t* debug_register(char* name, int pages, int nr_areas, +debug_info_t *debug_register(const char *name, int pages, int nr_areas, int buf_size); -debug_info_t *debug_register_mode(char *name, int pages, int nr_areas, +debug_info_t *debug_register_mode(const char *name, int pages, int nr_areas, int buf_size, mode_t mode, uid_t uid, gid_t gid); -- cgit v1.1 From f16f5843507ceaea315dae82b9fee29a65b72f24 Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Thu, 15 May 2008 16:52:36 +0200 Subject: [S390] dasd: fix timeout handling in interrupt handler When the dasd_int_handler is called with an error code instead of an irb, the associated request should be restarted. This handling was missing from the -ETIMEDOUT case. In fact it should be done in any case. Signed-off-by: Stefan Weinhuber Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index ac6d4d3..8ba3f13 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -925,6 +925,8 @@ static void dasd_handle_killed_request(struct ccw_device *cdev, struct dasd_ccw_req *cqr; struct dasd_device *device; + if (!intparm) + return; cqr = (struct dasd_ccw_req *) intparm; if (cqr->status != DASD_CQR_IN_IO) { MESSAGE(KERN_DEBUG, @@ -976,17 +978,16 @@ void dasd_int_handler(struct ccw_device *cdev, unsigned long intparm, if (IS_ERR(irb)) { switch (PTR_ERR(irb)) { case -EIO: - dasd_handle_killed_request(cdev, intparm); break; case -ETIMEDOUT: printk(KERN_WARNING"%s(%s): request timed out\n", __func__, cdev->dev.bus_id); - //FIXME - dasd uses own timeout interface... break; default: printk(KERN_WARNING"%s(%s): unknown error %ld\n", __func__, cdev->dev.bus_id, PTR_ERR(irb)); } + dasd_handle_killed_request(cdev, intparm); return; } -- cgit v1.1 From f455adcff102851629d716815f92bb7010de0c4e Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Thu, 15 May 2008 16:52:37 +0200 Subject: [S390] tape: Use ccw_dev_id to build cdev_id. To construct the integer containing the information from the bus_id, it is easier to use the data from ccw_dev_id than to parse the bus_id. Signed-off-by: Cornelia Huck Signed-off-by: Martin Schwidefsky --- drivers/s390/char/tape_core.c | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-) diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 7ad8cf1..76e44eb 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c @@ -76,32 +76,9 @@ const char *tape_op_verbose[TO_SIZE] = [TO_KEKL_QUERY] = "KLQ",[TO_RDC] = "RDC", }; -static int -busid_to_int(char *bus_id) +static int devid_to_int(struct ccw_dev_id *dev_id) { - int dec; - int d; - char * s; - - for(s = bus_id, d = 0; *s != '\0' && *s != '.'; s++) - d = (d * 10) + (*s - '0'); - dec = d; - for(s++, d = 0; *s != '\0' && *s != '.'; s++) - d = (d * 10) + (*s - '0'); - dec = (dec << 8) + d; - - for(s++; *s != '\0'; s++) { - if (*s >= '0' && *s <= '9') { - d = *s - '0'; - } else if (*s >= 'a' && *s <= 'f') { - d = *s - 'a' + 10; - } else { - d = *s - 'A' + 10; - } - dec = (dec << 4) + d; - } - - return dec; + return dev_id->devno + (dev_id->ssid << 16); } /* @@ -551,6 +528,7 @@ tape_generic_probe(struct ccw_device *cdev) { struct tape_device *device; int ret; + struct ccw_dev_id dev_id; device = tape_alloc_device(); if (IS_ERR(device)) @@ -565,7 +543,8 @@ tape_generic_probe(struct ccw_device *cdev) cdev->dev.driver_data = device; cdev->handler = __tape_do_irq; device->cdev = cdev; - device->cdev_id = busid_to_int(cdev->dev.bus_id); + ccw_device_get_id(cdev, &dev_id); + device->cdev_id = devid_to_int(&dev_id); PRINT_INFO("tape device %s found\n", cdev->dev.bus_id); return ret; } -- cgit v1.1 From 85cb185dad54be308c3f3a6068dd7d418b8b53e4 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 15 May 2008 16:52:38 +0200 Subject: [S390] smp: __smp_call_function_map vs cpu_online_map fix. Both smp_call_function() and __smp_call_function_map() access cpu_online_map. Both functions run with preemption disabled which protects for cpus going offline. However new cpus can be added and therefore the cpu_online_map can change unexpectedly. So use the call_lock to protect against changes to the cpu_online_map in start_secondary() and all smp_call_* functions. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/smp.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 0aeb290..1f42289 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c @@ -139,7 +139,6 @@ static void __smp_call_function_map(void (*func) (void *info), void *info, if (wait) data.finished = CPU_MASK_NONE; - spin_lock(&call_lock); call_data = &data; for_each_cpu_mask(cpu, map) @@ -151,7 +150,6 @@ static void __smp_call_function_map(void (*func) (void *info), void *info, if (wait) while (!cpus_equal(map, data.finished)) cpu_relax(); - spin_unlock(&call_lock); out: if (local) { local_irq_disable(); @@ -177,11 +175,11 @@ int smp_call_function(void (*func) (void *info), void *info, int nonatomic, { cpumask_t map; - preempt_disable(); + spin_lock(&call_lock); map = cpu_online_map; cpu_clear(smp_processor_id(), map); __smp_call_function_map(func, info, nonatomic, wait, map); - preempt_enable(); + spin_unlock(&call_lock); return 0; } EXPORT_SYMBOL(smp_call_function); @@ -202,10 +200,10 @@ EXPORT_SYMBOL(smp_call_function); int smp_call_function_single(int cpu, void (*func) (void *info), void *info, int nonatomic, int wait) { - preempt_disable(); + spin_lock(&call_lock); __smp_call_function_map(func, info, nonatomic, wait, cpumask_of_cpu(cpu)); - preempt_enable(); + spin_unlock(&call_lock); return 0; } EXPORT_SYMBOL(smp_call_function_single); @@ -228,10 +226,10 @@ EXPORT_SYMBOL(smp_call_function_single); int smp_call_function_mask(cpumask_t mask, void (*func)(void *), void *info, int wait) { - preempt_disable(); + spin_lock(&call_lock); cpu_clear(smp_processor_id(), mask); __smp_call_function_map(func, info, 0, wait, mask); - preempt_enable(); + spin_unlock(&call_lock); return 0; } EXPORT_SYMBOL(smp_call_function_mask); @@ -592,7 +590,9 @@ int __cpuinit start_secondary(void *cpuvoid) pfault_init(); /* Mark this cpu as online */ + spin_lock(&call_lock); cpu_set(smp_processor_id(), cpu_online_map); + spin_unlock(&call_lock); /* Switch on interrupts */ local_irq_enable(); /* Print info about this processor */ -- cgit v1.1 From 8dd79cb1051723496bbdcea2247e49567cedb3ac Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Thu, 15 May 2008 16:52:39 +0200 Subject: [S390] show_interrupts: prevent cpu hotplug when walking cpu_online_map. Surround all the code withing show_interrupts() with get/put_online_cpus() to prevent strange results wrt cpu hotplug. Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- arch/s390/kernel/irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index c59a86d..e7c5bfb 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -25,6 +25,7 @@ int show_interrupts(struct seq_file *p, void *v) static const char *intrclass_names[] = { "EXT", "I/O", }; int i = *(loff_t *) v, j; + get_online_cpus(); if (i == 0) { seq_puts(p, " "); for_each_online_cpu(j) @@ -43,7 +44,7 @@ int show_interrupts(struct seq_file *p, void *v) seq_putc(p, '\n'); } - + put_online_cpus(); return 0; } -- cgit v1.1 From f54d8a1b3fef79bb1aa2f0840dd356ce7bb180f9 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Wed, 14 May 2008 15:14:52 -0400 Subject: parisc: Remove ioctl.h content picked up from . Now that allows overriding of the most commonly changed macro values, take advantage of that. Signed-off-by: Robert P. J. Day Signed-off-by: Kyle McMartin --- include/asm-parisc/ioctl.h | 51 +--------------------------------------------- 1 file changed, 1 insertion(+), 50 deletions(-) diff --git a/include/asm-parisc/ioctl.h b/include/asm-parisc/ioctl.h index 68338d2..ec8efa0 100644 --- a/include/asm-parisc/ioctl.h +++ b/include/asm-parisc/ioctl.h @@ -32,21 +32,6 @@ * NOTE: This limits the max parameter size to 16kB -1 ! */ -#define _IOC_NRBITS 8 -#define _IOC_TYPEBITS 8 -#define _IOC_SIZEBITS 14 -#define _IOC_DIRBITS 2 - -#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) -#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) -#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) -#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) - -#define _IOC_NRSHIFT 0 -#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) -#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) -#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) - /* * Direction bits. */ @@ -54,40 +39,6 @@ #define _IOC_WRITE 2U #define _IOC_READ 1U -#define _IOC(dir,type,nr,size) \ - (((dir) << _IOC_DIRSHIFT) | \ - ((type) << _IOC_TYPESHIFT) | \ - ((nr) << _IOC_NRSHIFT) | \ - ((size) << _IOC_SIZESHIFT)) - -/* provoke compile error for invalid uses of size argument */ -extern unsigned int __invalid_size_argument_for_IOC; -#define _IOC_TYPECHECK(t) \ - ((sizeof(t) == sizeof(t[1]) && \ - sizeof(t) < (1 << _IOC_SIZEBITS)) ? \ - sizeof(t) : __invalid_size_argument_for_IOC) - -/* used to create numbers */ -#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) -#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) -#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) -#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) -#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) -#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) -#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) - -/* used to decode ioctl numbers.. */ -#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) -#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) -#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) -#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) - -/* ...and for the drivers/sound files... */ - -#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT) -#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT) -#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT) -#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) -#define IOCSIZE_SHIFT (_IOC_SIZESHIFT) +#include #endif /* _ASM_PARISC_IOCTL_H */ -- cgit v1.1 From 872f6debcae63309eb39bfc2cc9462fb83450ee0 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Thu, 15 May 2008 10:53:57 -0400 Subject: parisc: use conditional macro for 64-bit wide ops This work enables us to remove -traditional from $AFLAGS on parisc. Signed-off-by: Kyle McMartin --- arch/parisc/kernel/entry.S | 46 ++++++++++++---------------- arch/parisc/kernel/pacache.S | 70 +++++++++++++++++++++---------------------- include/asm-parisc/assembly.h | 6 ++-- 3 files changed, 56 insertions(+), 66 deletions(-) diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 1a3935e..5d08374 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -41,16 +41,8 @@ #include #ifdef CONFIG_64BIT -#define CMPIB cmpib,* -#define CMPB cmpb,* -#define COND(x) *x - .level 2.0w #else -#define CMPIB cmpib, -#define CMPB cmpb, -#define COND(x) x - .level 2.0 #endif @@ -958,9 +950,9 @@ intr_check_sig: * Only do signals if we are returning to user space */ LDREG PT_IASQ0(%r16), %r20 - CMPIB=,n 0,%r20,intr_restore /* backward */ + cmpib,COND(=),n 0,%r20,intr_restore /* backward */ LDREG PT_IASQ1(%r16), %r20 - CMPIB=,n 0,%r20,intr_restore /* backward */ + cmpib,COND(=),n 0,%r20,intr_restore /* backward */ copy %r0, %r25 /* long in_syscall = 0 */ #ifdef CONFIG_64BIT @@ -1014,10 +1006,10 @@ intr_do_resched: * we jump back to intr_restore. */ LDREG PT_IASQ0(%r16), %r20 - CMPIB= 0, %r20, intr_do_preempt + cmpib,COND(=) 0, %r20, intr_do_preempt nop LDREG PT_IASQ1(%r16), %r20 - CMPIB= 0, %r20, intr_do_preempt + cmpib,COND(=) 0, %r20, intr_do_preempt nop #ifdef CONFIG_64BIT @@ -1046,7 +1038,7 @@ intr_do_preempt: /* current_thread_info()->preempt_count */ mfctl %cr30, %r1 LDREG TI_PRE_COUNT(%r1), %r19 - CMPIB<> 0, %r19, intr_restore /* if preempt_count > 0 */ + cmpib,COND(<>) 0, %r19, intr_restore /* if preempt_count > 0 */ nop /* prev insn branched backwards */ /* check if we interrupted a critical path */ @@ -1065,7 +1057,7 @@ intr_do_preempt: */ intr_extint: - CMPIB=,n 0,%r16,1f + cmpib,COND(=),n 0,%r16,1f get_stack_use_cr30 b,n 2f @@ -1100,7 +1092,7 @@ ENDPROC(syscall_exit_rfi) ENTRY(intr_save) /* for os_hpmc */ mfsp %sr7,%r16 - CMPIB=,n 0,%r16,1f + cmpib,COND(=),n 0,%r16,1f get_stack_use_cr30 b 2f copy %r8,%r26 @@ -1122,7 +1114,7 @@ ENTRY(intr_save) /* for os_hpmc */ * adjust isr/ior below. */ - CMPIB=,n 6,%r26,skip_save_ior + cmpib,COND(=),n 6,%r26,skip_save_ior mfctl %cr20, %r16 /* isr */ @@ -1451,11 +1443,11 @@ nadtlb_emulate: bb,>=,n %r9,26,nadtlb_nullify /* m bit not set, just nullify */ BL get_register,%r25 extrw,u %r9,15,5,%r8 /* Get index register # */ - CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ + cmpib,COND(=),n -1,%r1,nadtlb_fault /* have to use slow path */ copy %r1,%r24 BL get_register,%r25 extrw,u %r9,10,5,%r8 /* Get base register # */ - CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ + cmpib,COND(=),n -1,%r1,nadtlb_fault /* have to use slow path */ BL set_register,%r25 add,l %r1,%r24,%r1 /* doesn't affect c/b bits */ @@ -1487,7 +1479,7 @@ nadtlb_probe_check: cmpb,<>,n %r16,%r17,nadtlb_fault /* Must be probe,[rw]*/ BL get_register,%r25 /* Find the target register */ extrw,u %r9,31,5,%r8 /* Get target register */ - CMPIB=,n -1,%r1,nadtlb_fault /* have to use slow path */ + cmpib,COND(=),n -1,%r1,nadtlb_fault /* have to use slow path */ BL set_register,%r25 copy %r0,%r1 /* Write zero to target register */ b nadtlb_nullify /* Nullify return insn */ @@ -1571,12 +1563,12 @@ dbit_trap_20w: L3_ptep ptp,pte,t0,va,dbit_fault #ifdef CONFIG_SMP - CMPIB=,n 0,spc,dbit_nolock_20w + cmpib,COND(=),n 0,spc,dbit_nolock_20w load32 PA(pa_dbit_lock),t0 dbit_spin_20w: LDCW 0(t0),t1 - cmpib,= 0,t1,dbit_spin_20w + cmpib,COND(=) 0,t1,dbit_spin_20w nop dbit_nolock_20w: @@ -1587,7 +1579,7 @@ dbit_nolock_20w: idtlbt pte,prot #ifdef CONFIG_SMP - CMPIB=,n 0,spc,dbit_nounlock_20w + cmpib,COND(=),n 0,spc,dbit_nounlock_20w ldi 1,t1 stw t1,0(t0) @@ -1607,7 +1599,7 @@ dbit_trap_11: L2_ptep ptp,pte,t0,va,dbit_fault #ifdef CONFIG_SMP - CMPIB=,n 0,spc,dbit_nolock_11 + cmpib,COND(=),n 0,spc,dbit_nolock_11 load32 PA(pa_dbit_lock),t0 dbit_spin_11: @@ -1629,7 +1621,7 @@ dbit_nolock_11: mtsp t1, %sr1 /* Restore sr1 */ #ifdef CONFIG_SMP - CMPIB=,n 0,spc,dbit_nounlock_11 + cmpib,COND(=),n 0,spc,dbit_nounlock_11 ldi 1,t1 stw t1,0(t0) @@ -1647,7 +1639,7 @@ dbit_trap_20: L2_ptep ptp,pte,t0,va,dbit_fault #ifdef CONFIG_SMP - CMPIB=,n 0,spc,dbit_nolock_20 + cmpib,COND(=),n 0,spc,dbit_nolock_20 load32 PA(pa_dbit_lock),t0 dbit_spin_20: @@ -1666,7 +1658,7 @@ dbit_nolock_20: idtlbt pte,prot #ifdef CONFIG_SMP - CMPIB=,n 0,spc,dbit_nounlock_20 + cmpib,COND(=),n 0,spc,dbit_nounlock_20 ldi 1,t1 stw t1,0(t0) @@ -1995,7 +1987,7 @@ ENTRY(syscall_exit) /* We can't use "CMPIB<> PER_HPUX" since "im5" field is sign extended */ ldo -PER_HPUX(%r19), %r19 - CMPIB<>,n 0,%r19,1f + cmpib,COND(<>),n 0,%r19,1f /* Save other hpux returns if personality is PER_HPUX */ STREG %r22,TASK_PT_GR22(%r1) diff --git a/arch/parisc/kernel/pacache.S b/arch/parisc/kernel/pacache.S index 7e4a339..e3246a5 100644 --- a/arch/parisc/kernel/pacache.S +++ b/arch/parisc/kernel/pacache.S @@ -86,7 +86,7 @@ ENTRY(flush_tlb_all_local) LDREG ITLB_OFF_COUNT(%r1), %arg2 LDREG ITLB_LOOP(%r1), %arg3 - ADDIB= -1, %arg3, fitoneloop /* Preadjust and test */ + addib,COND(=) -1, %arg3, fitoneloop /* Preadjust and test */ movb,<,n %arg3, %r31, fitdone /* If loop < 0, skip */ copy %arg0, %r28 /* Init base addr */ @@ -96,14 +96,14 @@ fitmanyloop: /* Loop if LOOP >= 2 */ copy %arg2, %r29 /* Init middle loop count */ fitmanymiddle: /* Loop if LOOP >= 2 */ - ADDIB> -1, %r31, fitmanymiddle /* Adjusted inner loop decr */ + addib,COND(>) -1, %r31, fitmanymiddle /* Adjusted inner loop decr */ pitlbe 0(%sr1, %r28) pitlbe,m %arg1(%sr1, %r28) /* Last pitlbe and addr adjust */ - ADDIB> -1, %r29, fitmanymiddle /* Middle loop decr */ + addib,COND(>) -1, %r29, fitmanymiddle /* Middle loop decr */ copy %arg3, %r31 /* Re-init inner loop count */ movb,tr %arg0, %r28, fitmanyloop /* Re-init base addr */ - ADDIB<=,n -1, %r22, fitdone /* Outer loop count decr */ + addib,COND(<=),n -1, %r22, fitdone /* Outer loop count decr */ fitoneloop: /* Loop if LOOP = 1 */ mtsp %r20, %sr1 @@ -111,10 +111,10 @@ fitoneloop: /* Loop if LOOP = 1 */ copy %arg2, %r29 /* init middle loop count */ fitonemiddle: /* Loop if LOOP = 1 */ - ADDIB> -1, %r29, fitonemiddle /* Middle loop count decr */ + addib,COND(>) -1, %r29, fitonemiddle /* Middle loop count decr */ pitlbe,m %arg1(%sr1, %r28) /* pitlbe for one loop */ - ADDIB> -1, %r22, fitoneloop /* Outer loop count decr */ + addib,COND(>) -1, %r22, fitoneloop /* Outer loop count decr */ add %r21, %r20, %r20 /* increment space */ fitdone: @@ -129,7 +129,7 @@ fitdone: LDREG DTLB_OFF_COUNT(%r1), %arg2 LDREG DTLB_LOOP(%r1), %arg3 - ADDIB= -1, %arg3, fdtoneloop /* Preadjust and test */ + addib,COND(=) -1, %arg3, fdtoneloop /* Preadjust and test */ movb,<,n %arg3, %r31, fdtdone /* If loop < 0, skip */ copy %arg0, %r28 /* Init base addr */ @@ -139,14 +139,14 @@ fdtmanyloop: /* Loop if LOOP >= 2 */ copy %arg2, %r29 /* Init middle loop count */ fdtmanymiddle: /* Loop if LOOP >= 2 */ - ADDIB> -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */ + addib,COND(>) -1, %r31, fdtmanymiddle /* Adjusted inner loop decr */ pdtlbe 0(%sr1, %r28) pdtlbe,m %arg1(%sr1, %r28) /* Last pdtlbe and addr adjust */ - ADDIB> -1, %r29, fdtmanymiddle /* Middle loop decr */ + addib,COND(>) -1, %r29, fdtmanymiddle /* Middle loop decr */ copy %arg3, %r31 /* Re-init inner loop count */ movb,tr %arg0, %r28, fdtmanyloop /* Re-init base addr */ - ADDIB<=,n -1, %r22,fdtdone /* Outer loop count decr */ + addib,COND(<=),n -1, %r22,fdtdone /* Outer loop count decr */ fdtoneloop: /* Loop if LOOP = 1 */ mtsp %r20, %sr1 @@ -154,10 +154,10 @@ fdtoneloop: /* Loop if LOOP = 1 */ copy %arg2, %r29 /* init middle loop count */ fdtonemiddle: /* Loop if LOOP = 1 */ - ADDIB> -1, %r29, fdtonemiddle /* Middle loop count decr */ + addib,COND(>) -1, %r29, fdtonemiddle /* Middle loop count decr */ pdtlbe,m %arg1(%sr1, %r28) /* pdtlbe for one loop */ - ADDIB> -1, %r22, fdtoneloop /* Outer loop count decr */ + addib,COND(>) -1, %r22, fdtoneloop /* Outer loop count decr */ add %r21, %r20, %r20 /* increment space */ @@ -210,18 +210,18 @@ ENTRY(flush_instruction_cache_local) LDREG ICACHE_COUNT(%r1), %arg2 LDREG ICACHE_LOOP(%r1), %arg3 rsm PSW_SM_I, %r22 /* No mmgt ops during loop*/ - ADDIB= -1, %arg3, fioneloop /* Preadjust and test */ + addib,COND(=) -1, %arg3, fioneloop /* Preadjust and test */ movb,<,n %arg3, %r31, fisync /* If loop < 0, do sync */ fimanyloop: /* Loop if LOOP >= 2 */ - ADDIB> -1, %r31, fimanyloop /* Adjusted inner loop decr */ + addib,COND(>) -1, %r31, fimanyloop /* Adjusted inner loop decr */ fice %r0(%sr1, %arg0) fice,m %arg1(%sr1, %arg0) /* Last fice and addr adjust */ movb,tr %arg3, %r31, fimanyloop /* Re-init inner loop count */ - ADDIB<=,n -1, %arg2, fisync /* Outer loop decr */ + addib,COND(<=),n -1, %arg2, fisync /* Outer loop decr */ fioneloop: /* Loop if LOOP = 1 */ - ADDIB> -1, %arg2, fioneloop /* Outer loop count decr */ + addib,COND(>) -1, %arg2, fioneloop /* Outer loop count decr */ fice,m %arg1(%sr1, %arg0) /* Fice for one loop */ fisync: @@ -251,18 +251,18 @@ ENTRY(flush_data_cache_local) LDREG DCACHE_COUNT(%r1), %arg2 LDREG DCACHE_LOOP(%r1), %arg3 rsm PSW_SM_I, %r22 - ADDIB= -1, %arg3, fdoneloop /* Preadjust and test */ + addib,COND(=) -1, %arg3, fdoneloop /* Preadjust and test */ movb,<,n %arg3, %r31, fdsync /* If loop < 0, do sync */ fdmanyloop: /* Loop if LOOP >= 2 */ - ADDIB> -1, %r31, fdmanyloop /* Adjusted inner loop decr */ + addib,COND(>) -1, %r31, fdmanyloop /* Adjusted inner loop decr */ fdce %r0(%sr1, %arg0) fdce,m %arg1(%sr1, %arg0) /* Last fdce and addr adjust */ movb,tr %arg3, %r31, fdmanyloop /* Re-init inner loop count */ - ADDIB<=,n -1, %arg2, fdsync /* Outer loop decr */ + addib,COND(<=),n -1, %arg2, fdsync /* Outer loop decr */ fdoneloop: /* Loop if LOOP = 1 */ - ADDIB> -1, %arg2, fdoneloop /* Outer loop count decr */ + addib,COND(>) -1, %arg2, fdoneloop /* Outer loop count decr */ fdce,m %arg1(%sr1, %arg0) /* Fdce for one loop */ fdsync: @@ -343,7 +343,7 @@ ENTRY(copy_user_page_asm) * non-taken backward branch. Note that .+4 is a backwards branch. * The ldd should only get executed if the branch is taken. */ - ADDIB>,n -1, %r1, 1b /* bundle 10 */ + addib,COND(>),n -1, %r1, 1b /* bundle 10 */ ldd 0(%r25), %r19 /* start next loads */ #else @@ -392,7 +392,7 @@ ENTRY(copy_user_page_asm) stw %r21, 56(%r26) stw %r22, 60(%r26) ldo 64(%r26), %r26 - ADDIB>,n -1, %r1, 1b + addib,COND(>),n -1, %r1, 1b ldw 0(%r25), %r19 #endif bv %r0(%r2) @@ -516,7 +516,7 @@ ENTRY(copy_user_page_asm) stw %r21, 56(%r28) stw %r22, 60(%r28) ldo 64(%r28), %r28 - ADDIB> -1, %r1,1b + addib,COND(>) -1, %r1,1b ldo 64(%r29), %r29 bv %r0(%r2) @@ -575,7 +575,7 @@ ENTRY(__clear_user_page_asm) std %r0, 104(%r28) std %r0, 112(%r28) std %r0, 120(%r28) - ADDIB> -1, %r1, 1b + addib,COND(>) -1, %r1, 1b ldo 128(%r28), %r28 #else /* ! CONFIG_64BIT */ @@ -598,7 +598,7 @@ ENTRY(__clear_user_page_asm) stw %r0, 52(%r28) stw %r0, 56(%r28) stw %r0, 60(%r28) - ADDIB> -1, %r1, 1b + addib,COND(>) -1, %r1, 1b ldo 64(%r28), %r28 #endif /* CONFIG_64BIT */ @@ -641,7 +641,7 @@ ENTRY(flush_kernel_dcache_page_asm) fdc,m %r23(%r26) fdc,m %r23(%r26) fdc,m %r23(%r26) - CMPB<< %r26, %r25,1b + cmpb,COND(<<) %r26, %r25,1b fdc,m %r23(%r26) sync @@ -684,7 +684,7 @@ ENTRY(flush_user_dcache_page) fdc,m %r23(%sr3, %r26) fdc,m %r23(%sr3, %r26) fdc,m %r23(%sr3, %r26) - CMPB<< %r26, %r25,1b + cmpb,COND(<<) %r26, %r25,1b fdc,m %r23(%sr3, %r26) sync @@ -727,7 +727,7 @@ ENTRY(flush_user_icache_page) fic,m %r23(%sr3, %r26) fic,m %r23(%sr3, %r26) fic,m %r23(%sr3, %r26) - CMPB<< %r26, %r25,1b + cmpb,COND(<<) %r26, %r25,1b fic,m %r23(%sr3, %r26) sync @@ -770,7 +770,7 @@ ENTRY(purge_kernel_dcache_page) pdc,m %r23(%r26) pdc,m %r23(%r26) pdc,m %r23(%r26) - CMPB<< %r26, %r25, 1b + cmpb,COND(<<) %r26, %r25, 1b pdc,m %r23(%r26) sync @@ -834,7 +834,7 @@ ENTRY(flush_alias_page) fdc,m %r23(%r28) fdc,m %r23(%r28) fdc,m %r23(%r28) - CMPB<< %r28, %r29, 1b + cmpb,COND(<<) %r28, %r29, 1b fdc,m %r23(%r28) sync @@ -857,7 +857,7 @@ flush_user_dcache_range_asm: ldo -1(%r23), %r21 ANDCM %r26, %r21, %r26 -1: CMPB<<,n %r26, %r25, 1b +1: cmpb,COND(<<),n %r26, %r25, 1b fdc,m %r23(%sr3, %r26) sync @@ -878,7 +878,7 @@ ENTRY(flush_kernel_dcache_range_asm) ldo -1(%r23), %r21 ANDCM %r26, %r21, %r26 -1: CMPB<<,n %r26, %r25,1b +1: cmpb,COND(<<),n %r26, %r25,1b fdc,m %r23(%r26) sync @@ -900,7 +900,7 @@ ENTRY(flush_user_icache_range_asm) ldo -1(%r23), %r21 ANDCM %r26, %r21, %r26 -1: CMPB<<,n %r26, %r25,1b +1: cmpb,COND(<<),n %r26, %r25,1b fic,m %r23(%sr3, %r26) sync @@ -943,7 +943,7 @@ ENTRY(flush_kernel_icache_page) fic,m %r23(%sr4, %r26) fic,m %r23(%sr4, %r26) fic,m %r23(%sr4, %r26) - CMPB<< %r26, %r25, 1b + cmpb,COND(<<) %r26, %r25, 1b fic,m %r23(%sr4, %r26) sync @@ -964,7 +964,7 @@ ENTRY(flush_kernel_icache_range_asm) ldo -1(%r23), %r21 ANDCM %r26, %r21, %r26 -1: CMPB<<,n %r26, %r25, 1b +1: cmpb,COND(<<),n %r26, %r25, 1b fic,m %r23(%sr4, %r26) sync diff --git a/include/asm-parisc/assembly.h b/include/asm-parisc/assembly.h index 5587f00..ffb2088 100644 --- a/include/asm-parisc/assembly.h +++ b/include/asm-parisc/assembly.h @@ -31,9 +31,8 @@ #define STREGM std,ma #define SHRREG shrd #define SHLREG shld -#define ADDIB addib,* -#define CMPB cmpb,* #define ANDCM andcm,* +#define COND(x) * ## x #define RP_OFFSET 16 #define FRAME_SIZE 128 #define CALLEE_REG_FRAME_SIZE 144 @@ -46,9 +45,8 @@ #define STREGM stwm #define SHRREG shr #define SHLREG shlw -#define ADDIB addib, -#define CMPB cmpb, #define ANDCM andcm +#define COND(x) x #define RP_OFFSET 20 #define FRAME_SIZE 64 #define CALLEE_REG_FRAME_SIZE 128 -- cgit v1.1 From 3378f7ec6cbc04c64ec8512847ac96fb7f376d93 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Thu, 15 May 2008 10:56:36 -0400 Subject: parisc: remove -traditional from assembler flags Signed-off-by: Kyle McMartin --- arch/parisc/kernel/Makefile | 3 --- 1 file changed, 3 deletions(-) diff --git a/arch/parisc/kernel/Makefile b/arch/parisc/kernel/Makefile index 1f6585a..016d3fc 100644 --- a/arch/parisc/kernel/Makefile +++ b/arch/parisc/kernel/Makefile @@ -4,9 +4,6 @@ extra-y := init_task.o head.o vmlinux.lds -AFLAGS_entry.o := -traditional -AFLAGS_pacache.o := -traditional - obj-y := cache.o pacache.o setup.o traps.o time.o irq.o \ pa7300lc.o syscall.o entry.o sys_parisc.o firmware.o \ ptrace.o hardware.o inventory.o drivers.o \ -- cgit v1.1 From c913f94d86d75492af6222d268c53df236194afb Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Thu, 15 May 2008 10:57:33 -0400 Subject: arch/parisc/kernel/perf_asm.S: build fix Missing header for __HEAD macro. Signed-off-by: Kyle McMartin --- arch/parisc/kernel/perf_asm.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/parisc/kernel/perf_asm.S b/arch/parisc/kernel/perf_asm.S index b2a9d05..d411dfb 100644 --- a/arch/parisc/kernel/perf_asm.S +++ b/arch/parisc/kernel/perf_asm.S @@ -20,6 +20,8 @@ */ #include + +#include #include #ifdef CONFIG_64BIT -- cgit v1.1 From 839052d27e8db0c1545256fe5827abcd00fb51c5 Mon Sep 17 00:00:00 2001 From: "Huang, Xiaolan" Date: Thu, 15 May 2008 10:18:41 +0800 Subject: [IA64] fix personality(PER_LINUX32) performance issue The patch aims to fix a performance issue for the syscall personality(PER_LINUX32). On IA-64 box, the syscall personality (PER_LINUX32) has poor performance because it failed to find the Linux/x86 execution domain. Then it tried to load the kernel module however it failed always and it used the default execution domain PER_LINUX instead. Requesting kernel modules is very expensive. It caused the performance issue. (see the function lookup_exec_domain in kernel/exec_domain.c). To resolve the issue, execution domain Linux/x86 is always registered in initialization time for IA-64 architecture. Signed-off-by: Xiaolan Huang Signed-off-by: Tony Luck --- arch/ia64/ia32/ia32_support.c | 10 ---------- arch/ia64/mm/init.c | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/arch/ia64/ia32/ia32_support.c b/arch/ia64/ia32/ia32_support.c index 896b1eb..a6965dd 100644 --- a/arch/ia64/ia32/ia32_support.c +++ b/arch/ia64/ia32/ia32_support.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -29,7 +28,6 @@ extern int die_if_kernel (char *str, struct pt_regs *regs, long err); -struct exec_domain ia32_exec_domain; struct page *ia32_shared_page[NR_CPUS]; unsigned long *ia32_boot_gdt; unsigned long *cpu_gdt_table[NR_CPUS]; @@ -240,14 +238,6 @@ ia32_cpu_init (void) static int __init ia32_init (void) { - ia32_exec_domain.name = "Linux/x86"; - ia32_exec_domain.handler = NULL; - ia32_exec_domain.pers_low = PER_LINUX32; - ia32_exec_domain.pers_high = PER_LINUX32; - ia32_exec_domain.signal_map = default_exec_domain.signal_map; - ia32_exec_domain.signal_invmap = default_exec_domain.signal_invmap; - register_exec_domain(&ia32_exec_domain); - #if PAGE_SHIFT > IA32_PAGE_SHIFT { extern struct kmem_cache *ia64_partial_page_cachep; diff --git a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c index fc6c663..200100e 100644 --- a/arch/ia64/mm/init.c +++ b/arch/ia64/mm/init.c @@ -719,3 +719,28 @@ out: EXPORT_SYMBOL_GPL(remove_memory); #endif /* CONFIG_MEMORY_HOTREMOVE */ #endif + +/* + * Even when CONFIG_IA32_SUPPORT is not enabled it is + * useful to have the Linux/x86 domain registered to + * avoid an attempted module load when emulators call + * personality(PER_LINUX32). This saves several milliseconds + * on each such call. + */ +static struct exec_domain ia32_exec_domain; + +static int __init +per_linux32_init(void) +{ + ia32_exec_domain.name = "Linux/x86"; + ia32_exec_domain.handler = NULL; + ia32_exec_domain.pers_low = PER_LINUX32; + ia32_exec_domain.pers_high = PER_LINUX32; + ia32_exec_domain.signal_map = default_exec_domain.signal_map; + ia32_exec_domain.signal_invmap = default_exec_domain.signal_invmap; + register_exec_domain(&ia32_exec_domain); + + return 0; +} + +__initcall(per_linux32_init); -- cgit v1.1 From 487ad7efbf6b0ec338cdfc2a7b0fbeb53f17a94c Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Wed, 14 May 2008 17:11:46 +0200 Subject: tty: fix BKL related leak and crash Enabling the BKL to be lockdep tracked uncovered the following upstream kernel bug in the tty code, which caused a BKL reference leak: ================================================ [ BUG: lock held when returning to user space! ] ------------------------------------------------ dmesg/3121 is leaving the kernel with locks still held! 1 lock held by dmesg/3121: #0: (kernel_mutex){--..}, at: [] opost+0x24/0x194 this might explain some of the atomicity warnings and crashes that -tip tree testing has been experiencing since the BKL was converted back to a spinlock. Signed-off-by: Ingo Molnar Signed-off-by: Linus Torvalds --- drivers/char/n_tty.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index 19105ec..8096389 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c @@ -282,16 +282,20 @@ static int opost(unsigned char c, struct tty_struct *tty) if (O_ONLRET(tty)) tty->column = 0; if (O_ONLCR(tty)) { - if (space < 2) + if (space < 2) { + unlock_kernel(); return -1; + } tty_put_char(tty, '\r'); tty->column = 0; } tty->canon_column = tty->column; break; case '\r': - if (O_ONOCR(tty) && tty->column == 0) + if (O_ONOCR(tty) && tty->column == 0) { + unlock_kernel(); return 0; + } if (O_OCRNL(tty)) { c = '\n'; if (O_ONLRET(tty)) @@ -303,10 +307,13 @@ static int opost(unsigned char c, struct tty_struct *tty) case '\t': spaces = 8 - (tty->column & 7); if (O_TABDLY(tty) == XTABS) { - if (space < spaces) + if (space < spaces) { + unlock_kernel(); return -1; + } tty->column += spaces; tty->ops->write(tty, " ", spaces); + unlock_kernel(); return 0; } tty->column += spaces; -- cgit v1.1 From 519deca0496a4df07d15acf3181ca5d573bffdec Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Thu, 15 May 2008 14:43:20 -0400 Subject: ext4: Retry block allocation if new blocks are allocated from system zone. If the block allocator gets blocks out of system zone ext4 calls ext4_error. But if the file system is mounted with errors=continue retry block allocation. We need to mark the system zone blocks as in use to make sure retry don't pick them again System zone is the block range mapping block bitmap, inode bitmap and inode table. Signed-off-by: Aneesh Kumar K.V Signed-off-by: Mingming Cao Signed-off-by: "Theodore Ts'o" --- fs/ext4/balloc.c | 17 +++++++++++------ fs/ext4/mballoc.c | 47 ++++++++++++++++++++++++++++++++++++----------- 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index da99437..30494c5 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -287,11 +287,11 @@ read_block_bitmap(struct super_block *sb, ext4_group_t block_group) (int)block_group, (unsigned long long)bitmap_blk); return NULL; } - if (!ext4_valid_block_bitmap(sb, desc, block_group, bh)) { - put_bh(bh); - return NULL; - } - + ext4_valid_block_bitmap(sb, desc, block_group, bh); + /* + * file system mounted not to panic on error, + * continue with corrupt bitmap + */ return bh; } /* @@ -1770,7 +1770,12 @@ allocated: "Allocating block in system zone - " "blocks from %llu, length %lu", ret_block, num); - goto out; + /* + * claim_block marked the blocks we allocated + * as in use. So we may want to selectively + * mark some of the blocks as free + */ + goto retry_alloc; } performed_allocation = 1; diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 1d7fde9..873ad9b 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -2736,7 +2736,7 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, struct ext4_sb_info *sbi; struct super_block *sb; ext4_fsblk_t block; - int err; + int err, len; BUG_ON(ac->ac_status != AC_STATUS_FOUND); BUG_ON(ac->ac_b_ex.fe_len <= 0); @@ -2770,14 +2770,27 @@ ext4_mb_mark_diskspace_used(struct ext4_allocation_context *ac, + ac->ac_b_ex.fe_start + le32_to_cpu(es->s_first_data_block); - if (block == ext4_block_bitmap(sb, gdp) || - block == ext4_inode_bitmap(sb, gdp) || - in_range(block, ext4_inode_table(sb, gdp), - EXT4_SB(sb)->s_itb_per_group)) { - + len = ac->ac_b_ex.fe_len; + if (in_range(ext4_block_bitmap(sb, gdp), block, len) || + in_range(ext4_inode_bitmap(sb, gdp), block, len) || + in_range(block, ext4_inode_table(sb, gdp), + EXT4_SB(sb)->s_itb_per_group) || + in_range(block + len - 1, ext4_inode_table(sb, gdp), + EXT4_SB(sb)->s_itb_per_group)) { ext4_error(sb, __func__, "Allocating block in system zone - block = %llu", block); + /* File system mounted not to panic on error + * Fix the bitmap and repeat the block allocation + * We leak some of the blocks here. + */ + mb_set_bits(sb_bgl_lock(sbi, ac->ac_b_ex.fe_group), + bitmap_bh->b_data, ac->ac_b_ex.fe_start, + ac->ac_b_ex.fe_len); + err = ext4_journal_dirty_metadata(handle, bitmap_bh); + if (!err) + err = -EAGAIN; + goto out_err; } #ifdef AGGRESSIVE_CHECK { @@ -4032,7 +4045,6 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, ac->ac_op = EXT4_MB_HISTORY_ALLOC; ext4_mb_normalize_request(ac, ar); - repeat: /* allocate space in core */ ext4_mb_regular_allocator(ac); @@ -4046,10 +4058,21 @@ repeat: } if (likely(ac->ac_status == AC_STATUS_FOUND)) { - ext4_mb_mark_diskspace_used(ac, handle); - *errp = 0; - block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex); - ar->len = ac->ac_b_ex.fe_len; + *errp = ext4_mb_mark_diskspace_used(ac, handle); + if (*errp == -EAGAIN) { + ac->ac_b_ex.fe_group = 0; + ac->ac_b_ex.fe_start = 0; + ac->ac_b_ex.fe_len = 0; + ac->ac_status = AC_STATUS_CONTINUE; + goto repeat; + } else if (*errp) { + ac->ac_b_ex.fe_len = 0; + ar->len = 0; + ext4_mb_show_ac(ac); + } else { + block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex); + ar->len = ac->ac_b_ex.fe_len; + } } else { freed = ext4_mb_discard_preallocations(sb, ac->ac_o_ex.fe_len); if (freed) @@ -4236,6 +4259,8 @@ do_more: ext4_error(sb, __func__, "Freeing blocks in system zone - " "Block = %lu, count = %lu", block, count); + /* err = 0. ext4_std_error should be a no op */ + goto error_return; } BUFFER_TRACE(bitmap_bh, "getting write access"); -- cgit v1.1 From 02c471cb17203c748e9bc87003052c1f46e5df69 Mon Sep 17 00:00:00 2001 From: Mingming Cao Date: Thu, 15 May 2008 14:46:17 -0400 Subject: jbd2: update transaction t_state to T_COMMIT fix Updating the current transaction's t_state is protected by j_state_lock. We need to do the same when updating the t_state to T_COMMIT. Acked-by: Jan Kara Signed-off-by: Mingming Cao Signed-off-by: "Theodore Ts'o" Signed-off-by: Andrew Morton --- fs/jbd2/commit.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index e013978..4d99685 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c @@ -560,7 +560,9 @@ void jbd2_journal_commit_transaction(journal_t *journal) * transaction! Now comes the tricky part: we need to write out * metadata. Loop over the transaction's entire buffer list: */ + spin_lock(&journal->j_state_lock); commit_transaction->t_state = T_COMMIT; + spin_unlock(&journal->j_state_lock); stats.u.run.rs_logging = jiffies; stats.u.run.rs_flushing = jbd2_time_diff(stats.u.run.rs_flushing, -- cgit v1.1 From a442ac512f36981182e66a427ad05f449ff6593b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 15 May 2008 17:50:37 -0700 Subject: Clean up 'print_fn_descriptor_symbol()' types Everybody wants to pass it a function pointer, and in fact, that is what you _must_ pass it for it to make sense (since it knows that ia64 and ppc64 use descriptors for function pointers and fetches the actual address from there). So don't make the argument be a 'unsigned long' and force everybody to add a cast. Signed-off-by: Linus Torvalds --- drivers/base/power/main.c | 2 +- drivers/pci/quirks.c | 3 +-- drivers/pnp/quirks.c | 3 +-- include/linux/kallsyms.h | 24 ++++++++++++++---------- init/main.c | 9 +++------ 5 files changed, 20 insertions(+), 21 deletions(-) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 7b76fd3..45cc3d9 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -418,7 +418,7 @@ void __suspend_report_result(const char *function, void *fn, int ret) { if (ret) { printk(KERN_ERR "%s(): ", function); - print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn); + print_fn_descriptor_symbol("%s returns ", fn); printk("%d\n", ret); } } diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index f2d9c77..dabb563 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -1503,8 +1503,7 @@ static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_f (f->device == dev->device || f->device == (u16) PCI_ANY_ID)) { #ifdef DEBUG dev_dbg(&dev->dev, "calling "); - print_fn_descriptor_symbol("%s()\n", - (unsigned long) f->hook); + print_fn_descriptor_symbol("%s\n", f->hook); #endif f->hook(dev); } diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c index ffdb12a..e2b7de4 100644 --- a/drivers/pnp/quirks.c +++ b/drivers/pnp/quirks.c @@ -331,8 +331,7 @@ void pnp_fixup_device(struct pnp_dev *dev) continue; #ifdef DEBUG dev_dbg(&dev->dev, "%s: calling ", f->id); - print_fn_descriptor_symbol("%s\n", - (unsigned long) f->quirk_function); + print_fn_descriptor_symbol("%s\n", f->quirk_function); #endif f->quirk_function(dev); } diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h index 82de2fb..00c1801 100644 --- a/include/linux/kallsyms.h +++ b/include/linux/kallsyms.h @@ -83,16 +83,6 @@ __attribute__((format(printf,1,2))); static inline void __check_printsym_format(const char *fmt, ...) { } -/* ia64 and ppc64 use function descriptors, which contain the real address */ -#if defined(CONFIG_IA64) || defined(CONFIG_PPC64) -#define print_fn_descriptor_symbol(fmt, addr) \ -do { \ - unsigned long *__faddr = (unsigned long*) addr; \ - print_symbol(fmt, __faddr[0]); \ -} while (0) -#else -#define print_fn_descriptor_symbol(fmt, addr) print_symbol(fmt, addr) -#endif static inline void print_symbol(const char *fmt, unsigned long addr) { @@ -101,6 +91,20 @@ static inline void print_symbol(const char *fmt, unsigned long addr) __builtin_extract_return_addr((void *)addr)); } +/* + * Pretty-print a function pointer. + * + * ia64 and ppc64 function pointers are really function descriptors, + * which contain a pointer the real address. + */ +static inline void print_fn_descriptor_symbol(const char *fmt, void *addr) +{ +#if defined(CONFIG_IA64) || defined(CONFIG_PPC64) + addr = *(void **)addr; +#endif + print_symbol(fmt, (unsigned long)addr); +} + #ifndef CONFIG_64BIT #define print_ip_sym(ip) \ do { \ diff --git a/init/main.c b/init/main.c index f406fef..c622151 100644 --- a/init/main.c +++ b/init/main.c @@ -706,8 +706,7 @@ static void __init do_initcalls(void) int result; if (initcall_debug) { - print_fn_descriptor_symbol("calling %s()\n", - (unsigned long) *call); + print_fn_descriptor_symbol("calling %s\n", *call); t0 = ktime_get(); } @@ -717,8 +716,7 @@ static void __init do_initcalls(void) t1 = ktime_get(); delta = ktime_sub(t1, t0); - print_fn_descriptor_symbol("initcall %s()", - (unsigned long) *call); + print_fn_descriptor_symbol("initcall %s", *call); printk(" returned %d after %Ld msecs\n", result, (unsigned long long) delta.tv64 >> 20); } @@ -737,8 +735,7 @@ static void __init do_initcalls(void) local_irq_enable(); } if (msgbuf[0]) { - print_fn_descriptor_symbol(KERN_WARNING "initcall %s()", - (unsigned long) *call); + print_fn_descriptor_symbol(KERN_WARNING "initcall %s", *call); printk(" returned with %s\n", msgbuf); } } -- cgit v1.1 From e0df154f45e40677781e971daec6c430cb34716b Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Thu, 15 May 2008 18:14:01 -0700 Subject: Split up 'do_initcalls()' into two simpler functions One function to just loop over the entries, one function to actually do the call and the associated debugging code. Signed-off-by: Linus Torvalds --- init/main.c | 77 ++++++++++++++++++++++++++++++++----------------------------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/init/main.c b/init/main.c index c622151..b8bcf6d 100644 --- a/init/main.c +++ b/init/main.c @@ -693,52 +693,57 @@ static int __init initcall_debug_setup(char *str) } __setup("initcall_debug", initcall_debug_setup); -extern initcall_t __initcall_start[], __initcall_end[]; - -static void __init do_initcalls(void) +static void __init do_one_initcall(initcall_t fn) { - initcall_t *call; int count = preempt_count(); + ktime_t t0, t1, delta; + char msgbuf[40]; + int result; - for (call = __initcall_start; call < __initcall_end; call++) { - ktime_t t0, t1, delta; - char msgbuf[40]; - int result; - - if (initcall_debug) { - print_fn_descriptor_symbol("calling %s\n", *call); - t0 = ktime_get(); - } + if (initcall_debug) { + print_fn_descriptor_symbol("calling %s\n", fn); + t0 = ktime_get(); + } - result = (*call)(); + result = fn(); - if (initcall_debug) { - t1 = ktime_get(); - delta = ktime_sub(t1, t0); + if (initcall_debug) { + t1 = ktime_get(); + delta = ktime_sub(t1, t0); - print_fn_descriptor_symbol("initcall %s", *call); - printk(" returned %d after %Ld msecs\n", result, - (unsigned long long) delta.tv64 >> 20); - } + print_fn_descriptor_symbol("initcall %s", fn); + printk(" returned %d after %Ld msecs\n", result, + (unsigned long long) delta.tv64 >> 20); + } - msgbuf[0] = 0; + msgbuf[0] = 0; - if (result && result != -ENODEV && initcall_debug) - sprintf(msgbuf, "error code %d ", result); + if (result && result != -ENODEV && initcall_debug) + sprintf(msgbuf, "error code %d ", result); - if (preempt_count() != count) { - strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf)); - preempt_count() = count; - } - if (irqs_disabled()) { - strncat(msgbuf, "disabled interrupts ", sizeof(msgbuf)); - local_irq_enable(); - } - if (msgbuf[0]) { - print_fn_descriptor_symbol(KERN_WARNING "initcall %s", *call); - printk(" returned with %s\n", msgbuf); - } + if (preempt_count() != count) { + strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf)); + preempt_count() = count; } + if (irqs_disabled()) { + strncat(msgbuf, "disabled interrupts ", sizeof(msgbuf)); + local_irq_enable(); + } + if (msgbuf[0]) { + print_fn_descriptor_symbol(KERN_WARNING "initcall %s", fn); + printk(" returned with %s\n", msgbuf); + } +} + + +extern initcall_t __initcall_start[], __initcall_end[]; + +static void __init do_initcalls(void) +{ + initcall_t *call; + + for (call = __initcall_start; call < __initcall_end; call++) + do_one_initcall(*call); /* Make sure there is no pending stuff from the initcall sequence */ flush_scheduled_work(); -- cgit v1.1 From a76bfd0da2321ed0a978ccbef192856ce7ed687a Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Thu, 15 May 2008 13:52:41 -0700 Subject: initcalls: Fix m68k build and possible buffer overflow This patch fixes a build bug on m68k - gcc decides to emit a call to the strlen library function, which we don't implement. More importantly - my previous patch "init: don't lose initcall return values" (commit e662e1cfd434aa234b72fbc781f1d70211cb785b) had introduced potential buffer overflow by wrong calculation of string accumulator size. Use strlcat() instead, fixing both bugs. Many thanks Andreas Schwab and Geert Uytterhoeven for helping to catch and fix the bug. Signed-off-by: Cyrill Gorcunov Cc: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- init/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/init/main.c b/init/main.c index b8bcf6d..f7fb200 100644 --- a/init/main.c +++ b/init/main.c @@ -697,7 +697,7 @@ static void __init do_one_initcall(initcall_t fn) { int count = preempt_count(); ktime_t t0, t1, delta; - char msgbuf[40]; + char msgbuf[64]; int result; if (initcall_debug) { @@ -722,11 +722,11 @@ static void __init do_one_initcall(initcall_t fn) sprintf(msgbuf, "error code %d ", result); if (preempt_count() != count) { - strncat(msgbuf, "preemption imbalance ", sizeof(msgbuf)); + strlcat(msgbuf, "preemption imbalance ", sizeof(msgbuf)); preempt_count() = count; } if (irqs_disabled()) { - strncat(msgbuf, "disabled interrupts ", sizeof(msgbuf)); + strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf)); local_irq_enable(); } if (msgbuf[0]) { -- cgit v1.1