From c21986a76220919bb06e4c04a89a8a62aeac107e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 4 Mar 2009 00:18:11 -0800 Subject: jsflash: stop defining MAJOR_NR Ever since early 2.5 kernels block drivers don't need to define MAJOR_NR anymore, so use the JSFD_MAJOR defined directly and kill it. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/sbus/char/jsflash.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c index a9a9893a5f95..e6d1fc8c54f1 100644 --- a/drivers/sbus/char/jsflash.c +++ b/drivers/sbus/char/jsflash.c @@ -38,9 +38,6 @@ #include #include #include - -#define MAJOR_NR JSFD_MAJOR - #include #include #include -- cgit v1.2.3 From f4c13638185c91a269c63fcfb980d89180cf43a1 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Wed, 4 Mar 2009 00:19:28 -0800 Subject: sparc64: wait_event_interruptible_timeout may return -ERESTARTSYS wait_event_interruptible_timeout may return -ERESTARTSYS. Signed-off-by: Roel Kluin Signed-off-by: David S. Miller --- drivers/sbus/char/bbc_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index f08e169ba1b5..7e30e5f6e032 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -129,7 +129,7 @@ static int wait_for_pin(struct bbc_i2c_bus *bp, u8 *status) bp->waiting = 1; add_wait_queue(&bp->wq, &wait); while (limit-- > 0) { - unsigned long val; + long val; val = wait_event_interruptible_timeout( bp->wq, -- cgit v1.2.3 From 33dd6f92a1a7ad85c54d47fd9d73371a32c0bde4 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 20 Feb 2009 06:53:48 -0700 Subject: [SCSI] sd: Don't try to spin up drives that are connected to an inactive port We currently try to spin up drives connected to standby and unavailable ports. This will never succeed and wastes a lot of time. Fail quickly if the sense data reports the port is in standby or unavailable state. Reported-by: Narayanan Rengarajan Tested-by: Narayanan Rengarajan Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 55310dbc10a6..4970ae4a62d6 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1167,23 +1167,19 @@ sd_spinup_disk(struct scsi_disk *sdkp) /* * The device does not want the automatic start to be issued. */ - if (sdkp->device->no_start_on_add) { + if (sdkp->device->no_start_on_add) break; - } - - /* - * If manual intervention is required, or this is an - * absent USB storage device, a spinup is meaningless. - */ - if (sense_valid && - sshdr.sense_key == NOT_READY && - sshdr.asc == 4 && sshdr.ascq == 3) { - break; /* manual intervention required */ - /* - * Issue command to spin up drive when not ready - */ - } else if (sense_valid && sshdr.sense_key == NOT_READY) { + if (sense_valid && sshdr.sense_key == NOT_READY) { + if (sshdr.asc == 4 && sshdr.ascq == 3) + break; /* manual intervention required */ + if (sshdr.asc == 4 && sshdr.ascq == 0xb) + break; /* standby */ + if (sshdr.asc == 4 && sshdr.ascq == 0xc) + break; /* unavailable */ + /* + * Issue command to spin up drive when not ready + */ if (!spintime) { sd_printk(KERN_NOTICE, sdkp, "Spinning up disk..."); cmd[0] = START_STOP; -- cgit v1.2.3 From d2c452306ab402d7a3572bc3bf8e575796529bf8 Mon Sep 17 00:00:00 2001 From: Gregory Lardiere Date: Sun, 22 Feb 2009 17:54:11 -0300 Subject: V4L/DVB (10789): m5602-s5k4aa: Split up the initial sensor probe in chunks. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous probe rotine tried to read 6 bytes in one chunk which currently isn't allowed. This is the rev. 10346 243399e67c41 readded with a high priority. Signed-off-by: Gregory Lardiere Signed-off-by: Erik Andrén Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index e564a61a72d7..48892b5715d5 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -102,7 +102,11 @@ int s5k4aa_probe(struct sd *sd) } /* Test some registers, but we don't know their exact meaning yet */ - if (m5602_read_sensor(sd, 0x00, prod_id, sizeof(prod_id))) + if (m5602_read_sensor(sd, 0x00, prod_id, 2)) + return -ENODEV; + if (m5602_read_sensor(sd, 0x02, prod_id+2, 2)) + return -ENODEV; + if (m5602_read_sensor(sd, 0x04, prod_id+4, 2)) return -ENODEV; if (memcmp(prod_id, expected_prod_id, sizeof(prod_id))) -- cgit v1.2.3 From 4c6c390eb8ba0c569279266a98c604508c695ef8 Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Thu, 5 Mar 2009 13:03:32 -0300 Subject: V4L/DVB (10832): tvaudio: Avoid breakage with tda9874a The 'bytes' array is 64 bytes large but the easy standard programming (TDA9874A_ESP) has a number of 255, outside the shadow array size. This patch increases the size of the shadow array in order to accomodate this register. Signed-off-by: Vitaly Wool Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 5aeccb301cea..076ed5bf48b1 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -54,7 +54,7 @@ MODULE_LICENSE("GPL"); /* ---------------------------------------------------------------------- */ /* our structs */ -#define MAXREGS 64 +#define MAXREGS 256 struct CHIPSTATE; typedef int (*getvalue)(int); -- cgit v1.2.3 From e08e7b5f01de7ec246b996c65e9c26c7cea0c62d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 5 Mar 2009 16:19:14 -0300 Subject: V4L/DVB (10834): zoran: auto-select bt866 for AverMedia 6 Eyes AFAIK, the bt866 is only seen on AverMedia 6 Eyes. However, no module selects it. Adds a proper select for this driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/video/zoran/Kconfig index 4ea5fa71de89..8666e19f31a7 100644 --- a/drivers/media/video/zoran/Kconfig +++ b/drivers/media/video/zoran/Kconfig @@ -68,6 +68,7 @@ config VIDEO_ZORAN_AVS6EYES tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1 select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_BT866 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO help Support for the AverMedia 6 Eyes video surveillance card. -- cgit v1.2.3 From 1f6ff364ceda516f88351a8ab640e656beed0b26 Mon Sep 17 00:00:00 2001 From: Abhijeet Joglekar Date: Fri, 27 Feb 2009 10:54:35 -0800 Subject: [SCSI] libfc: Pass lport in exch_mgr_reset fc_exch_mgr structure is private to fc_exch.c. To export exch_mgr_reset to transport, transport needs access to the exch manager. Change exch_mgr_reset to use lport param which is the shared structure between libFC and transport. Alternatively, fc_exch_mgr definition can be moved to libfc.h so that lport can be accessed from mp*. Signed-off-by: Abhijeet Joglekar Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 3 ++- drivers/scsi/libfc/fc_lport.c | 4 ++-- drivers/scsi/libfc/fc_rport.c | 4 ++-- include/scsi/libfc.h | 4 ++-- 4 files changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 66db08a5f27f..a09416fd843c 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1480,10 +1480,11 @@ static void fc_exch_reset(struct fc_exch *ep) * If sid is non-zero, reset only exchanges we source from that FID. * If did is non-zero, reset only exchanges destined to that FID. */ -void fc_exch_mgr_reset(struct fc_exch_mgr *mp, u32 sid, u32 did) +void fc_exch_mgr_reset(struct fc_lport *lp, u32 sid, u32 did) { struct fc_exch *ep; struct fc_exch *next; + struct fc_exch_mgr *mp = lp->emp; spin_lock_bh(&mp->em_lock); restart: diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 0b9bdb1fb807..5db223ce3b25 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -663,7 +663,7 @@ int fc_lport_destroy(struct fc_lport *lport) { lport->tt.frame_send = fc_frame_drop; lport->tt.fcp_abort_io(lport); - lport->tt.exch_mgr_reset(lport->emp, 0, 0); + lport->tt.exch_mgr_reset(lport, 0, 0); return 0; } EXPORT_SYMBOL(fc_lport_destroy); @@ -973,7 +973,7 @@ static void fc_lport_enter_reset(struct fc_lport *lport) lport->tt.disc_stop(lport); - lport->tt.exch_mgr_reset(lport->emp, 0, 0); + lport->tt.exch_mgr_reset(lport, 0, 0); fc_host_fabric_name(lport->host) = 0; fc_host_port_id(lport->host) = 0; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index e780d8caf70e..dec7bae0e56d 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1285,7 +1285,7 @@ void fc_rport_terminate_io(struct fc_rport *rport) struct fc_rport_libfc_priv *rdata = rport->dd_data; struct fc_lport *lport = rdata->local_port; - lport->tt.exch_mgr_reset(lport->emp, 0, rport->port_id); - lport->tt.exch_mgr_reset(lport->emp, rport->port_id, 0); + lport->tt.exch_mgr_reset(lport, 0, rport->port_id); + lport->tt.exch_mgr_reset(lport, rport->port_id, 0); } EXPORT_SYMBOL(fc_rport_terminate_io); diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 9f2876397dda..042f4ade73d7 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -472,7 +472,7 @@ struct libfc_function_template { * If s_id is non-zero, reset only exchanges originating from that FID. * If d_id is non-zero, reset only exchanges sending to that FID. */ - void (*exch_mgr_reset)(struct fc_exch_mgr *, + void (*exch_mgr_reset)(struct fc_lport *, u32 s_id, u32 d_id); void (*rport_flush_queue)(void); @@ -916,7 +916,7 @@ struct fc_seq *fc_seq_start_next(struct fc_seq *sp); * If s_id is non-zero, reset only exchanges originating from that FID. * If d_id is non-zero, reset only exchanges sending to that FID. */ -void fc_exch_mgr_reset(struct fc_exch_mgr *, u32 s_id, u32 d_id); +void fc_exch_mgr_reset(struct fc_lport *, u32 s_id, u32 d_id); /* * Functions for fc_functions_template -- cgit v1.2.3 From 571f824c3cd7b7f5a40ba100f7e576b6b0fe826a Mon Sep 17 00:00:00 2001 From: Abhijeet Joglekar Date: Fri, 27 Feb 2009 10:54:41 -0800 Subject: [SCSI] libfc: when rport goes away (re-plogi), clean up exchanges to/from rport When a rport goes away, libFC does a plogi which will reset exchanges at the rport. Clean exchanges at our end, both in transport and libFC. If transport hooks into exch_mgr_reset, it will call back into fc_exch_mgr_reset() to clean up libFC exchanges. Signed-off-by: Abhijeet Joglekar Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_rport.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index dec7bae0e56d..717575934152 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -214,6 +214,7 @@ static void fc_rport_state_enter(struct fc_rport *rport, static void fc_rport_work(struct work_struct *work) { + u32 port_id; struct fc_rport_libfc_priv *rdata = container_of(work, struct fc_rport_libfc_priv, event_work); enum fc_rport_event event; @@ -279,8 +280,12 @@ static void fc_rport_work(struct work_struct *work) rport_ops->event_callback(lport, rport, event); if (trans_state == FC_PORTSTATE_ROGUE) put_device(&rport->dev); - else + else { + port_id = rport->port_id; fc_remote_port_delete(rport); + lport->tt.exch_mgr_reset(lport, 0, port_id); + lport->tt.exch_mgr_reset(lport, port_id, 0); + } } else mutex_unlock(&rdata->rp_mutex); } -- cgit v1.2.3 From 78342da3682ec843e3e6301af5c723c88a46c408 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Fri, 27 Feb 2009 10:54:46 -0800 Subject: [SCSI] libfc: handle RRQ exch timeout Cleanup exchange held due to RRQ when RRQ exch times out, in this case the ABTS is already done causing RRQ req therefore proceeding with cleanup in fc_exch_rrq_resp should be okay to restore exch resource. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index a09416fd843c..e874e77b740c 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1608,7 +1608,7 @@ static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg) if (IS_ERR(fp)) { int err = PTR_ERR(fp); - if (err == -FC_EX_CLOSED) + if (err == -FC_EX_CLOSED || err == -FC_EX_TIMEOUT) goto cleanup; FC_DBG("Cannot process RRQ, because of frame error %d\n", err); return; -- cgit v1.2.3 From a7e84f2b83f17f8f11da34ccef3ba5a862dc0182 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Fri, 27 Feb 2009 10:54:51 -0800 Subject: [SCSI] libfc: fixed a soft lockup issue in fc_exch_recv_abts The fc_seq_start_next grabs ep->ex_lock but this lock was already held here, so instead called fc_seq_start_next_locked to avoid soft lockup. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index e874e77b740c..dd269e5f953e 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1096,7 +1096,7 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp) ap->ba_high_seq_cnt = fh->fh_seq_cnt; ap->ba_low_seq_cnt = htons(sp->cnt); } - sp = fc_seq_start_next(sp); + sp = fc_seq_start_next_locked(sp); spin_unlock_bh(&ep->ex_lock); fc_seq_send_last(sp, fp, FC_RCTL_BA_ACC, FC_TYPE_BLS); fc_frame_free(rx_fp); -- cgit v1.2.3 From bc0e17f691085315ae9303eb5b0883fe16dfe6b1 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Fri, 27 Feb 2009 10:54:57 -0800 Subject: [SCSI] libfc, fcoe: fixed locking issues with lport->lp_mutex around lport->link_status The fcoe_xmit could call fc_pause in case the pending skb queue len is larger than FCOE_MAX_QUEUE_DEPTH, the fc_pause was trying to grab lport->lp_muex to change lport->link_status and that had these issues :- 1. The fcoe_xmit was getting called with bh disabled, thus causing "BUG: scheduling while atomic" when grabbing lport->lp_muex with bh disabled. 2. fc_linkup and fc_linkdown function calls lport_enter function with lport->lp_mutex held and these enter function in turn calls fcoe_xmit to send lport related FC frame, e.g. fc_linkup => fc_lport_enter_flogi to send flogi req. In this case grabbing the same lport->lp_mutex again in fc_puase from fcoe_xmit would cause deadlock. The lport->lp_mutex was used for setting FC_PAUSE in fcoe_xmit path but FC_PAUSE bit was not used anywhere beside just setting and clear this bit in lport->link_status, instead used a separate field qfull in fc_lport to eliminate need for lport->lp_mutex to track pending queue full condition and in turn avoid above described two locking issues. Also added check for lp->qfull in fc_fcp_lport_queue_ready to trigger SCSI_MLQUEUE_HOST_BUSY when lp->qfull is set to prevent more scsi-ml cmds while lp->qfull is set. This patch eliminated FC_LINK_UP and FC_PAUSE and instead used dedicated fields in fc_lport for this, this simplified all related conditional code. Also removed fc_pause and fc_unpause functions and instead used newly added lport->qfull directly in fcoe. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe_sw.c | 6 +++--- drivers/scsi/fcoe/libfcoe.c | 41 +++++++++++++++++------------------------ drivers/scsi/libfc/fc_fcp.c | 4 ++-- drivers/scsi/libfc/fc_lport.c | 36 ++++++------------------------------ include/scsi/libfc.h | 12 ++---------- 5 files changed, 30 insertions(+), 69 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index dc4cd5e25760..cf83675a0fb9 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -116,7 +116,8 @@ static int fcoe_sw_lport_config(struct fc_lport *lp) { int i = 0; - lp->link_status = 0; + lp->link_up = 0; + lp->qfull = 0; lp->max_retry_count = 3; lp->e_d_tov = 2 * 1000; /* FC-FS default */ lp->r_a_tov = 2 * 2 * 1000; @@ -181,9 +182,8 @@ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) if (fc_set_mfs(lp, mfs)) return -EINVAL; - lp->link_status = ~FC_PAUSE & ~FC_LINK_UP; if (!fcoe_link_ok(lp)) - lp->link_status |= FC_LINK_UP; + lp->link_up = 1; /* offload features support */ if (fc->real_dev->features & NETIF_F_SG) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index e419f486cdb3..296071043f55 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -504,7 +504,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) if (rc) { fcoe_insert_wait_queue(lp, skb); if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - fc_pause(lp); + lp->qfull = 1; } return 0; @@ -718,7 +718,7 @@ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) * fcoe_watchdog - fcoe timer callback * @vp: * - * This checks the pending queue length for fcoe and put fcoe to be paused state + * This checks the pending queue length for fcoe and set lport qfull * if the FCOE_MAX_QUEUE_DEPTH is reached. This is done for all fc_lport on the * fcoe_hostlist. * @@ -728,17 +728,17 @@ void fcoe_watchdog(ulong vp) { struct fc_lport *lp; struct fcoe_softc *fc; - int paused = 0; + int qfilled = 0; read_lock(&fcoe_hostlist_lock); list_for_each_entry(fc, &fcoe_hostlist, list) { lp = fc->lp; if (lp) { if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - paused = 1; + qfilled = 1; if (fcoe_check_wait_queue(lp) < FCOE_MAX_QUEUE_DEPTH) { - if (paused) - fc_unpause(lp); + if (qfilled) + lp->qfull = 0; } } } @@ -767,8 +767,7 @@ void fcoe_watchdog(ulong vp) **/ static int fcoe_check_wait_queue(struct fc_lport *lp) { - int rc, unpause = 0; - int paused = 0; + int rc; struct sk_buff *skb; struct fcoe_softc *fc; @@ -776,10 +775,10 @@ static int fcoe_check_wait_queue(struct fc_lport *lp) spin_lock_bh(&fc->fcoe_pending_queue.lock); /* - * is this interface paused? + * if interface pending queue full then set qfull in lport. */ if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - paused = 1; + lp->qfull = 1; if (fc->fcoe_pending_queue.qlen) { while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) { spin_unlock_bh(&fc->fcoe_pending_queue.lock); @@ -791,11 +790,9 @@ static int fcoe_check_wait_queue(struct fc_lport *lp) spin_lock_bh(&fc->fcoe_pending_queue.lock); } if (fc->fcoe_pending_queue.qlen < FCOE_MAX_QUEUE_DEPTH) - unpause = 1; + lp->qfull = 0; } spin_unlock_bh(&fc->fcoe_pending_queue.lock); - if ((unpause) && (paused)) - fc_unpause(lp); return fc->fcoe_pending_queue.qlen; } @@ -873,7 +870,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, struct net_device *real_dev = ptr; struct fcoe_softc *fc; struct fcoe_dev_stats *stats; - u16 new_status; + u32 new_link_up; u32 mfs; int rc = NOTIFY_OK; @@ -890,17 +887,15 @@ static int fcoe_device_notification(struct notifier_block *notifier, goto out; } - new_status = lp->link_status; + new_link_up = lp->link_up; switch (event) { case NETDEV_DOWN: case NETDEV_GOING_DOWN: - new_status &= ~FC_LINK_UP; + new_link_up = 0; break; case NETDEV_UP: case NETDEV_CHANGE: - new_status &= ~FC_LINK_UP; - if (!fcoe_link_ok(lp)) - new_status |= FC_LINK_UP; + new_link_up = !fcoe_link_ok(lp); break; case NETDEV_CHANGEMTU: mfs = fc->real_dev->mtu - @@ -908,17 +903,15 @@ static int fcoe_device_notification(struct notifier_block *notifier, sizeof(struct fcoe_crc_eof)); if (mfs >= FC_MIN_MAX_FRAME) fc_set_mfs(lp, mfs); - new_status &= ~FC_LINK_UP; - if (!fcoe_link_ok(lp)) - new_status |= FC_LINK_UP; + new_link_up = !fcoe_link_ok(lp); break; case NETDEV_REGISTER: break; default: FC_DBG("unknown event %ld call", event); } - if (lp->link_status != new_status) { - if ((new_status & FC_LINK_UP) == FC_LINK_UP) + if (lp->link_up != new_link_up) { + if (new_link_up) fc_linkup(lp); else { stats = lp->dev_stats[smp_processor_id()]; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 404e63ff46b8..f440aaca39c2 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1621,7 +1621,7 @@ out: static inline int fc_fcp_lport_queue_ready(struct fc_lport *lp) { /* lock ? */ - return (lp->state == LPORT_ST_READY) && (lp->link_status & FC_LINK_UP); + return (lp->state == LPORT_ST_READY) && lp->link_up && !lp->qfull; } /** @@ -1890,7 +1890,7 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd) lp = shost_priv(sc_cmd->device->host); if (lp->state != LPORT_ST_READY) return rc; - else if (!(lp->link_status & FC_LINK_UP)) + else if (!lp->link_up) return rc; spin_lock_irqsave(lp->host->host_lock, flags); diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 5db223ce3b25..a6ab692f5f51 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -250,7 +250,7 @@ void fc_get_host_port_state(struct Scsi_Host *shost) { struct fc_lport *lp = shost_priv(shost); - if ((lp->link_status & FC_LINK_UP) == FC_LINK_UP) + if (lp->link_up) fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; else fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; @@ -577,8 +577,8 @@ void fc_linkup(struct fc_lport *lport) fc_host_port_id(lport->host)); mutex_lock(&lport->lp_mutex); - if ((lport->link_status & FC_LINK_UP) != FC_LINK_UP) { - lport->link_status |= FC_LINK_UP; + if (!lport->link_up) { + lport->link_up = 1; if (lport->state == LPORT_ST_RESET) fc_lport_enter_flogi(lport); @@ -597,8 +597,8 @@ void fc_linkdown(struct fc_lport *lport) FC_DEBUG_LPORT("Link is down for port (%6x)\n", fc_host_port_id(lport->host)); - if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP) { - lport->link_status &= ~(FC_LINK_UP); + if (lport->link_up) { + lport->link_up = 0; fc_lport_enter_reset(lport); lport->tt.fcp_cleanup(lport); } @@ -606,30 +606,6 @@ void fc_linkdown(struct fc_lport *lport) } EXPORT_SYMBOL(fc_linkdown); -/** - * fc_pause - Pause the flow of frames - * @lport: The lport to be paused - */ -void fc_pause(struct fc_lport *lport) -{ - mutex_lock(&lport->lp_mutex); - lport->link_status |= FC_PAUSE; - mutex_unlock(&lport->lp_mutex); -} -EXPORT_SYMBOL(fc_pause); - -/** - * fc_unpause - Unpause the flow of frames - * @lport: The lport to be unpaused - */ -void fc_unpause(struct fc_lport *lport) -{ - mutex_lock(&lport->lp_mutex); - lport->link_status &= ~(FC_PAUSE); - mutex_unlock(&lport->lp_mutex); -} -EXPORT_SYMBOL(fc_unpause); - /** * fc_fabric_logoff - Logout of the fabric * @lport: fc_lport pointer to logoff the fabric @@ -977,7 +953,7 @@ static void fc_lport_enter_reset(struct fc_lport *lport) fc_host_fabric_name(lport->host) = 0; fc_host_port_id(lport->host) = 0; - if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP) + if (lport->link_up) fc_lport_enter_flogi(lport); } diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 042f4ade73d7..b9e6c1cd8914 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -68,9 +68,6 @@ /* * FC HBA status */ -#define FC_PAUSE (1 << 1) -#define FC_LINK_UP (1 << 0) - enum fc_lport_state { LPORT_ST_NONE = 0, LPORT_ST_FLOGI, @@ -603,7 +600,8 @@ struct fc_lport { /* Operational Information */ struct libfc_function_template tt; - u16 link_status; + u8 link_up; + u8 qfull; enum fc_lport_state state; unsigned long boot_time; @@ -703,12 +701,6 @@ void fc_linkup(struct fc_lport *); */ void fc_linkdown(struct fc_lport *); -/* - * Pause and unpause traffic. - */ -void fc_pause(struct fc_lport *); -void fc_unpause(struct fc_lport *); - /* * Configure the local port. */ -- cgit v1.2.3 From 6755db1cd4587084be85f860b7aa7c0cc9d776dc Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Fri, 27 Feb 2009 10:55:02 -0800 Subject: [SCSI] libfc: rport retry on LS_RJT from certain ELS This allows any rport ELS to retry on LS_RJT. The rport error handling would only retry on resource allocation failures and exchange timeouts. I have a target that will occasionally reject PLOGI when we do a quick LOGO/PLOGI. When a critical ELS was rejected, libfc would fail silently leaving the rport in a dead state. The retry count and delay are managed by fc_rport_error_retry. If the retry count is exceeded fc_rport_error will be called. When retrying is not the correct course of action, fc_rport_error can be called directly. Signed-off-by: Chris Leech Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 2 - drivers/scsi/libfc/fc_rport.c | 111 ++++++++++++++++++++++++------------------ include/scsi/fc/fc_fs.h | 5 ++ 3 files changed, 69 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index dd269e5f953e..8c4018956d4c 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -32,8 +32,6 @@ #include #include -#define FC_DEF_R_A_TOV (10 * 1000) /* resource allocation timeout */ - /* * fc_exch_debug can be set in debugger or at compile time to get more logs. */ diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 717575934152..600a8fffa940 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -81,6 +81,7 @@ static void fc_rport_recv_logo_req(struct fc_rport *, struct fc_seq *, struct fc_frame *); static void fc_rport_timeout(struct work_struct *); static void fc_rport_error(struct fc_rport *, struct fc_frame *); +static void fc_rport_error_retry(struct fc_rport *, struct fc_frame *); static void fc_rport_work(struct work_struct *); static const char *fc_rport_state_names[] = { @@ -410,57 +411,73 @@ static void fc_rport_timeout(struct work_struct *work) } /** - * fc_rport_error - Handler for any errors + * fc_rport_error - Error handler, called once retries have been exhausted * @rport: The fc_rport object * @fp: The frame pointer * - * If the error was caused by a resource allocation failure - * then wait for half a second and retry, otherwise retry - * immediately. - * * Locking Note: The rport lock is expected to be held before * calling this routine */ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp) { struct fc_rport_libfc_priv *rdata = rport->dd_data; - unsigned long delay = 0; FC_DEBUG_RPORT("Error %ld in state %s, retries %d\n", PTR_ERR(fp), fc_rport_state(rport), rdata->retries); - if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) { - /* - * Memory allocation failure, or the exchange timed out. - * Retry after delay - */ - if (rdata->retries < rdata->local_port->max_retry_count) { - rdata->retries++; - if (!fp) - delay = msecs_to_jiffies(500); - get_device(&rport->dev); - schedule_delayed_work(&rdata->retry_work, delay); - } else { - switch (rdata->rp_state) { - case RPORT_ST_PLOGI: - case RPORT_ST_PRLI: - case RPORT_ST_LOGO: - rdata->event = RPORT_EV_FAILED; - queue_work(rport_event_queue, - &rdata->event_work); - break; - case RPORT_ST_RTV: - fc_rport_enter_ready(rport); - break; - case RPORT_ST_NONE: - case RPORT_ST_READY: - case RPORT_ST_INIT: - break; - } - } + switch (rdata->rp_state) { + case RPORT_ST_PLOGI: + case RPORT_ST_PRLI: + case RPORT_ST_LOGO: + rdata->event = RPORT_EV_FAILED; + queue_work(rport_event_queue, + &rdata->event_work); + break; + case RPORT_ST_RTV: + fc_rport_enter_ready(rport); + break; + case RPORT_ST_NONE: + case RPORT_ST_READY: + case RPORT_ST_INIT: + break; } } +/** + * fc_rport_error_retry - Error handler when retries are desired + * @rport: The fc_rport object + * @fp: The frame pointer + * + * If the error was an exchange timeout retry immediately, + * otherwise wait for E_D_TOV. + * + * Locking Note: The rport lock is expected to be held before + * calling this routine + */ +static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp) +{ + struct fc_rport_libfc_priv *rdata = rport->dd_data; + unsigned long delay = FC_DEF_E_D_TOV; + + /* make sure this isn't an FC_EX_CLOSED error, never retry those */ + if (PTR_ERR(fp) == -FC_EX_CLOSED) + return fc_rport_error(rport, fp); + + if (rdata->retries < rdata->local_port->max_retry_count) { + FC_DEBUG_RPORT("Error %ld in state %s, retrying\n", + PTR_ERR(fp), fc_rport_state(rport)); + rdata->retries++; + /* no additional delay on exchange timeouts */ + if (PTR_ERR(fp) == -FC_EX_TIMEOUT) + delay = 0; + get_device(&rport->dev); + schedule_delayed_work(&rdata->retry_work, delay); + return; + } + + return fc_rport_error(rport, fp); +} + /** * fc_rport_plogi_recv_resp - Handle incoming ELS PLOGI response * @sp: current sequence in the PLOGI exchange @@ -495,7 +512,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, } if (IS_ERR(fp)) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); goto err; } @@ -527,7 +544,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, else fc_rport_enter_prli(rport); } else - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); out: fc_frame_free(fp); @@ -557,14 +574,14 @@ static void fc_rport_enter_plogi(struct fc_rport *rport) rport->maxframe_size = FC_MIN_MAX_PAYLOAD; fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi)); if (!fp) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); return; } rdata->e_d_tov = lport->e_d_tov; if (!lport->tt.elsct_send(lport, rport, fp, ELS_PLOGI, fc_rport_plogi_resp, rport, lport->e_d_tov)) - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); else get_device(&rport->dev); } @@ -604,7 +621,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, } if (IS_ERR(fp)) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); goto err; } @@ -662,7 +679,7 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, rport->port_id); if (IS_ERR(fp)) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); goto err; } @@ -712,13 +729,13 @@ static void fc_rport_enter_prli(struct fc_rport *rport) fp = fc_frame_alloc(lport, sizeof(*pp)); if (!fp) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); return; } if (!lport->tt.elsct_send(lport, rport, fp, ELS_PRLI, fc_rport_prli_resp, rport, lport->e_d_tov)) - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); else get_device(&rport->dev); } @@ -809,13 +826,13 @@ static void fc_rport_enter_rtv(struct fc_rport *rport) fp = fc_frame_alloc(lport, sizeof(struct fc_els_rtv)); if (!fp) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); return; } if (!lport->tt.elsct_send(lport, rport, fp, ELS_RTV, fc_rport_rtv_resp, rport, lport->e_d_tov)) - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); else get_device(&rport->dev); } @@ -840,13 +857,13 @@ static void fc_rport_enter_logo(struct fc_rport *rport) fp = fc_frame_alloc(lport, sizeof(struct fc_els_logo)); if (!fp) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); return; } if (!lport->tt.elsct_send(lport, rport, fp, ELS_LOGO, fc_rport_logo_resp, rport, lport->e_d_tov)) - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); else get_device(&rport->dev); } diff --git a/include/scsi/fc/fc_fs.h b/include/scsi/fc/fc_fs.h index 3e4801d2bdbb..1b7af3a64c7c 100644 --- a/include/scsi/fc/fc_fs.h +++ b/include/scsi/fc/fc_fs.h @@ -337,4 +337,9 @@ enum fc_pf_rjt_reason { FC_RJT_VENDOR = 0xff, /* vendor specific reject */ }; +/* default timeout values */ + +#define FC_DEF_E_D_TOV 2000UL +#define FC_DEF_R_A_TOV 10000UL + #endif /* _FC_FS_H_ */ -- cgit v1.2.3 From 26d9cab558f901051d0b69b2c445c8588931ce8d Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Fri, 27 Feb 2009 10:55:07 -0800 Subject: [SCSI] libfc: fixed a read IO data integrity issue when a IO data frame lost The fc_fcp_complete_locked detected data underrun in this case and set the FC_DATA_UNDRUN but that was ignored by fc_io_compl for all cases including read underrun. Added code to not to ignore FC_DATA_UNDRUN for read IO and instead suggested scsi-ml to retry cmd to recover from lost data frame. Not sure if it is okay to ignore FC_DATA_UNDRUN for other case, so let code as is for other cases but removed or-ing with zero valued fsp->cdb_status for those cases. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index f440aaca39c2..ecc72612c385 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1810,12 +1810,12 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) sc_cmd->result = DID_ERROR << 16; break; case FC_DATA_UNDRUN: - if (fsp->cdb_status == 0) { + if ((fsp->cdb_status == 0) && !(fsp->req_flags & FC_SRB_READ)) { /* * scsi status is good but transport level - * underrun. for read it should be an error?? + * underrun. */ - sc_cmd->result = (DID_OK << 16) | fsp->cdb_status; + sc_cmd->result = DID_OK << 16; } else { /* * scsi got underrun, this is an error -- cgit v1.2.3 From f7db2c150cf5082cf74555f30a1305938041de80 Mon Sep 17 00:00:00 2001 From: Steve Ma Date: Fri, 27 Feb 2009 10:55:13 -0800 Subject: [SCSI] libfc: exch mgr is freed while lport still retrying sequences When a sequence cannot be delivered to the target, the local port will schedule retries, While this process is in progress, if we destroy the FCoE interface, the fcoe_sw_destroy routine is entered, and the fc_exch_mgr_free(lp->emp) is called. Thus if fc_exch_alloc() is called when retrying the sequence, the mempool_alloc() will fail to allocate the exchange because the mempool of the exchange manager has already been released. This patch is to cancel any pending retry work of the local port before we start to destroy the interface. Also, when resetting the local port, we should also stop the scheduled pending retries. Signed-off-by: Steve Ma Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index a6ab692f5f51..e6ea4f119530 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -619,6 +619,7 @@ int fc_fabric_logoff(struct fc_lport *lport) mutex_lock(&lport->lp_mutex); fc_lport_enter_logo(lport); mutex_unlock(&lport->lp_mutex); + cancel_delayed_work_sync(&lport->retry_work); return 0; } EXPORT_SYMBOL(fc_fabric_logoff); @@ -918,6 +919,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, */ int fc_lport_reset(struct fc_lport *lport) { + cancel_delayed_work_sync(&lport->retry_work); mutex_lock(&lport->lp_mutex); fc_lport_enter_reset(lport); mutex_unlock(&lport->lp_mutex); -- cgit v1.2.3 From 5101ff99f59aefb72e0c96e82aa32048ac9f8425 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:18 -0800 Subject: [SCSI] libfc: Don't violate transport template for rogue port creation Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_disc.c | 6 +++--- drivers/scsi/libfc/fc_lport.c | 4 ++-- drivers/scsi/libfc/fc_rport.c | 3 +++ include/scsi/libfc.h | 5 +++++ 4 files changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index dd1564c9e04a..15e3f840c049 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -430,7 +430,7 @@ static int fc_disc_new_target(struct fc_disc *disc, dp.ids.port_name = ids->port_name; dp.ids.node_name = ids->node_name; dp.ids.roles = ids->roles; - rport = fc_rport_rogue_create(&dp); + rport = lport->tt.rport_create(&dp); } if (!rport) error = -ENOMEM; @@ -617,7 +617,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) if ((dp.ids.port_id != fc_host_port_id(lport->host)) && (dp.ids.port_name != lport->wwpn)) { - rport = fc_rport_rogue_create(&dp); + rport = lport->tt.rport_create(&dp); if (rport) { rdata = rport->dd_data; rdata->ops = &fc_disc_rport_ops; @@ -769,7 +769,7 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp) if (rport) fc_disc_del_target(disc, rport); - new_rport = fc_rport_rogue_create(dp); + new_rport = lport->tt.rport_create(dp); if (new_rport) { rdata = new_rport->dd_data; rdata->ops = &fc_disc_rport_ops; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index e6ea4f119530..07335ae2947c 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -232,7 +232,7 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, lport->ptp_rp = NULL; } - lport->ptp_rp = fc_rport_rogue_create(&dp); + lport->ptp_rp = lport->tt.rport_create(&dp); lport->tt.rport_login(lport->ptp_rp); @@ -1282,7 +1282,7 @@ static void fc_lport_enter_dns(struct fc_lport *lport) fc_lport_state_enter(lport, LPORT_ST_DNS); - rport = fc_rport_rogue_create(&dp); + rport = lport->tt.rport_create(&dp); if (!rport) goto err; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 600a8fffa940..81b3ca188789 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1271,6 +1271,9 @@ static void fc_rport_flush_queue(void) int fc_rport_init(struct fc_lport *lport) { + if (!lport->tt.rport_create) + lport->tt.rport_create = fc_rport_rogue_create; + if (!lport->tt.rport_login) lport->tt.rport_login = fc_rport_login; diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index b9e6c1cd8914..37df48e13b97 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -489,6 +489,11 @@ struct libfc_function_template { * Remote Port interfaces */ + /* + * Create a remote port + */ + struct fc_rport *(*rport_create)(struct fc_disc_port *); + /* * Initiates the RP state machine. It is called from the LP module. * This function will issue the following commands to the N_Port -- cgit v1.2.3 From 23f11f9076fcd6ee20c56e413b11f1b5658e3f82 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:23 -0800 Subject: [SCSI] libfc: correct RPORT_TO_PRIV usage We only need to use this macro when assigning a value to rport->dd_data. All other accesses should just use dd_data. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_disc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 15e3f840c049..9f4e408bc7fc 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -246,7 +246,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, list_del(&dp->peers); rport = lport->tt.rport_lookup(lport, dp->ids.port_id); if (rport) { - rdata = RPORT_TO_PRIV(rport); + rdata = rport->dd_data; list_del(&rdata->peers); lport->tt.rport_logoff(rport); } @@ -453,7 +453,7 @@ static int fc_disc_new_target(struct fc_disc *disc, static void fc_disc_del_target(struct fc_disc *disc, struct fc_rport *rport) { struct fc_lport *lport = disc->lport; - struct fc_rport_libfc_priv *rdata = RPORT_TO_PRIV(rport); + struct fc_rport_libfc_priv *rdata = rport->dd_data; list_del(&rdata->peers); lport->tt.rport_logoff(rport); } -- cgit v1.2.3 From d3b33327cab0c8e9cae2c12d908ca79433c0d1ac Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:29 -0800 Subject: [SCSI] libfc: rename rp to rdata in fc_disc_new_target() Just rename the variable as per our naming convention. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_disc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 9f4e408bc7fc..cfbce893941a 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -396,7 +396,7 @@ static int fc_disc_new_target(struct fc_disc *disc, struct fc_rport_identifiers *ids) { struct fc_lport *lport = disc->lport; - struct fc_rport_libfc_priv *rp; + struct fc_rport_libfc_priv *rdata; int error = 0; if (rport && ids->port_name) { @@ -436,9 +436,9 @@ static int fc_disc_new_target(struct fc_disc *disc, error = -ENOMEM; } if (rport) { - rp = rport->dd_data; - rp->ops = &fc_disc_rport_ops; - rp->rp_state = RPORT_ST_INIT; + rdata = rport->dd_data; + rdata->ops = &fc_disc_rport_ops; + rdata->rp_state = RPORT_ST_INIT; lport->tt.rport_login(rport); } } -- cgit v1.2.3 From efaf5c085dd2d31757b0ff7886970dfddd8d1808 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:34 -0800 Subject: [SCSI] libfc: check for err when recv and state is incorrect If we've just created an interface and the an rport is logging in we may have a request on the wire (say PRLI). If we destroy the interface, we'll go through each rport on the disc->rports list and set each rport's state to NONE. Then the lport will reset the EM. The EM reset will send a CLOSED event to the prli_resp() handler which will notice that the state != PRLI. In this case it frees the frame pointer, decrements the refcount and unlocks the rport. The problem is that there isn't a frame in this case. It's just a pointer with an embedded error code. The free causes an Oops. This patch moves the error checking to be before the state checking. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 50 +++++++++++++++++++++---------------------- drivers/scsi/libfc/fc_rport.c | 30 +++++++++++++------------- 2 files changed, 40 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 07335ae2947c..c00de2244c78 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1031,17 +1031,17 @@ static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a RFT_ID response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_RFT_ID) { FC_DBG("Received a RFT_ID response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - fh = fc_frame_header_get(fp); ct = fc_frame_payload_get(fp, sizeof(*ct)); @@ -1083,17 +1083,17 @@ static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a RPN_ID response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_RPN_ID) { FC_DBG("Received a RPN_ID response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - fh = fc_frame_header_get(fp); ct = fc_frame_payload_get(fp, sizeof(*ct)); if (fh && ct && fh->fh_type == FC_TYPE_CT && @@ -1133,17 +1133,17 @@ static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a SCR response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_SCR) { FC_DBG("Received a SCR response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) fc_lport_enter_ready(lport); @@ -1359,17 +1359,17 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a LOGO response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_LOGO) { FC_DBG("Received a LOGO response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) fc_lport_enter_reset(lport); @@ -1443,17 +1443,17 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a FLOGI response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_FLOGI) { FC_DBG("Received a FLOGI response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - fh = fc_frame_header_get(fp); did = ntoh24(fh->fh_d_id); if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) { diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 81b3ca188789..4f23a9bb15a1 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -505,17 +505,17 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n", rport->port_id); + if (IS_ERR(fp)) { + fc_rport_error_retry(rport, fp); + goto err; + } + if (rdata->rp_state != RPORT_ST_PLOGI) { FC_DBG("Received a PLOGI response, but in state %s\n", fc_rport_state(rport)); goto out; } - if (IS_ERR(fp)) { - fc_rport_error_retry(rport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC && (plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) { @@ -614,17 +614,17 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n", rport->port_id); + if (IS_ERR(fp)) { + fc_rport_error_retry(rport, fp); + goto err; + } + if (rdata->rp_state != RPORT_ST_PRLI) { FC_DBG("Received a PRLI response, but in state %s\n", fc_rport_state(rport)); goto out; } - if (IS_ERR(fp)) { - fc_rport_error_retry(rport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) { pp = fc_frame_payload_get(fp, sizeof(*pp)); @@ -764,17 +764,17 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n", rport->port_id); + if (IS_ERR(fp)) { + fc_rport_error(rport, fp); + goto err; + } + if (rdata->rp_state != RPORT_ST_RTV) { FC_DBG("Received a RTV response, but in state %s\n", fc_rport_state(rport)); goto out; } - if (IS_ERR(fp)) { - fc_rport_error(rport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) { struct fc_els_rtv_acc *rtv; -- cgit v1.2.3 From 0796e75503adc6b0a119493ce2e599fb5fd8f96e Mon Sep 17 00:00:00 2001 From: Friedrich Oslage Date: Sun, 8 Mar 2009 20:13:42 -0700 Subject: sunhme: Fix qfe parent detection. Signed-off-by: Friedrich Oslage Signed-off-by: David S. Miller --- drivers/net/sunhme.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index cc4013be5e18..0ff837a9c804 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2630,8 +2630,6 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) int err = -ENODEV; sbus_dp = to_of_device(op->dev.parent)->node; - if (is_qfe) - sbus_dp = to_of_device(op->dev.parent->parent)->node; /* We can match PCI devices too, do not accept those here. */ if (strcmp(sbus_dp->name, "sbus")) -- cgit v1.2.3 From 916c775ff297dc60219a4f0e5527ba6ab4a88ed4 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 9 Mar 2009 00:52:14 +0000 Subject: bnx2x: Adding restriction on sge_buf_size sge_buff_size may not be more than 0xffff. Reported-by: Bjorn Helgaas Signed-off-by: Vladislav Zolotarov Tested-by: Bjorn Helgaas Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index d3e7775a9ccf..48127f11d033 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -4518,7 +4518,8 @@ static void bnx2x_init_context(struct bnx2x *bp) (USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_TPA | USTORM_ETH_ST_CONTEXT_CONFIG_ENABLE_SGE_RING); context->ustorm_st_context.common.sge_buff_size = - (u16)(BCM_PAGE_SIZE*PAGES_PER_SGE); + (u16)min((u32)SGE_PAGE_SIZE*PAGES_PER_SGE, + (u32)0xffff); context->ustorm_st_context.common.sge_page_base_hi = U64_HI(fp->rx_sge_mapping); context->ustorm_st_context.common.sge_page_base_lo = -- cgit v1.2.3 From 6dc7d8c843024c2636cf52d3f93047acbcd765f2 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 9 Mar 2009 00:52:17 +0000 Subject: bnx2x: Casting page alignment Adding a proper cast to the argument of PAGE_ALIGN macro so that the output won't depend on its original type. Without this cast aligned value will be truncated to the size of the argument type. Reported-by: Bjorn Helgaas Signed-off-by: Vladislav Zolotarov Tested-by: Bjorn Helgaas Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index 15a5cf0f676b..3cf2b92eef3b 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -152,7 +152,7 @@ struct sw_rx_page { #define PAGES_PER_SGE (1 << PAGES_PER_SGE_SHIFT) #define SGE_PAGE_SIZE PAGE_SIZE #define SGE_PAGE_SHIFT PAGE_SHIFT -#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN(addr) +#define SGE_PAGE_ALIGN(addr) PAGE_ALIGN((typeof(PAGE_SIZE))addr) #define BCM_RX_ETH_PAYLOAD_ALIGN 64 -- cgit v1.2.3 From db434ac6bff0d991d0b60166dc9d6405b873d0f7 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 9 Mar 2009 00:52:21 +0000 Subject: bnx2x: Using DMAE to initialize the chip There was a bug, which occasionally caused failure in PRAM initialization after the cold boot. Also incremented version number to 1.45.27. Signed-off-by: Vladislav Zolotarov Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_init.h | 4 ---- drivers/net/bnx2x_main.c | 18 +++++++++--------- 2 files changed, 9 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2x_init.h b/drivers/net/bnx2x_init.h index a6c0b3abba29..3b0c2499ef17 100644 --- a/drivers/net/bnx2x_init.h +++ b/drivers/net/bnx2x_init.h @@ -150,7 +150,6 @@ static void bnx2x_init_ind_wr(struct bnx2x *bp, u32 addr, const u32 *data, static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len) { -#ifdef USE_DMAE int offset = 0; if (bp->dmae_ready) { @@ -164,9 +163,6 @@ static void bnx2x_write_big_buf(struct bnx2x *bp, u32 addr, u32 len) addr + offset, len); } else bnx2x_init_str_wr(bp, addr, bp->gunzip_buf, len); -#else - bnx2x_init_str_wr(bp, addr, bp->gunzip_buf, len); -#endif } static void bnx2x_init_fill(struct bnx2x *bp, u32 addr, int fill, u32 len) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 48127f11d033..2e346a5e98cf 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -57,7 +57,7 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.26" +#define DRV_MODULE_VERSION "1.45.27" #define DRV_MODULE_RELDATE "2009/01/26" #define BNX2X_BC_VER 0x040200 @@ -4035,10 +4035,10 @@ static void bnx2x_zero_sb(struct bnx2x *bp, int sb_id) { int port = BP_PORT(bp); - bnx2x_init_fill(bp, BAR_USTRORM_INTMEM + + bnx2x_init_fill(bp, USTORM_INTMEM_ADDR + USTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), 0, sizeof(struct ustorm_status_block)/4); - bnx2x_init_fill(bp, BAR_CSTRORM_INTMEM + + bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR + CSTORM_SB_HOST_STATUS_BLOCK_OFFSET(port, sb_id), 0, sizeof(struct cstorm_status_block)/4); } @@ -4092,18 +4092,18 @@ static void bnx2x_zero_def_sb(struct bnx2x *bp) { int func = BP_FUNC(bp); - bnx2x_init_fill(bp, BAR_USTRORM_INTMEM + + bnx2x_init_fill(bp, TSTORM_INTMEM_ADDR + + TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, + sizeof(struct tstorm_def_status_block)/4); + bnx2x_init_fill(bp, USTORM_INTMEM_ADDR + USTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, sizeof(struct ustorm_def_status_block)/4); - bnx2x_init_fill(bp, BAR_CSTRORM_INTMEM + + bnx2x_init_fill(bp, CSTORM_INTMEM_ADDR + CSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, sizeof(struct cstorm_def_status_block)/4); - bnx2x_init_fill(bp, BAR_XSTRORM_INTMEM + + bnx2x_init_fill(bp, XSTORM_INTMEM_ADDR + XSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, sizeof(struct xstorm_def_status_block)/4); - bnx2x_init_fill(bp, BAR_TSTRORM_INTMEM + - TSTORM_DEF_SB_HOST_STATUS_BLOCK_OFFSET(func), 0, - sizeof(struct tstorm_def_status_block)/4); } static void bnx2x_init_def_sb(struct bnx2x *bp, -- cgit v1.2.3 From 34f42a070fc98f5dc07e9fa2338b7b8d1dc347eb Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:45 -0800 Subject: [SCSI] libfc, fcoe: Fix kerneldoc comments 1) Added '()' for function names in kerneldoc comments 2) Changed comment bookends from '**/' to '*/'. The comment on the the mailing list was that '**/' "is consistently unconventional. Not wrong, just odd." The Documentation/kernel-doc-nano-HOWTO.txt states that kerneldoc comment blocks should end with '**/' but most (if not all) instance I found under drivers/scsi/ were only using the '*/' so I converted to that style. 3) Removed incorrect linebreaks in kerneldoc comments where found 4) Removed a few unnecessary blank comment lines in kerneldoc comment blocks Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fc_transport_fcoe.c | 77 ++++++++-------- drivers/scsi/fcoe/fcoe_sw.c | 42 ++++----- drivers/scsi/fcoe/libfcoe.c | 162 +++++++++++++++++----------------- drivers/scsi/libfc/fc_disc.c | 45 +++++----- drivers/scsi/libfc/fc_fcp.c | 46 +++++----- drivers/scsi/libfc/fc_lport.c | 77 ++++++++-------- drivers/scsi/libfc/fc_rport.c | 46 +++++----- include/scsi/libfc.h | 14 +-- 8 files changed, 252 insertions(+), 257 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fc_transport_fcoe.c b/drivers/scsi/fcoe/fc_transport_fcoe.c index bf7fe6fc0820..0eea4c434c31 100644 --- a/drivers/scsi/fcoe/fc_transport_fcoe.c +++ b/drivers/scsi/fcoe/fc_transport_fcoe.c @@ -33,19 +33,19 @@ static LIST_HEAD(fcoe_transports); static DEFINE_MUTEX(fcoe_transports_lock); /** - * fcoe_transport_default - returns ptr to the default transport fcoe_sw - **/ + * fcoe_transport_default() - Returns ptr to the default transport fcoe_sw + */ struct fcoe_transport *fcoe_transport_default(void) { return &fcoe_sw_transport; } /** - * fcoe_transport_to_pcidev - get the pci dev from a netdev + * fcoe_transport_to_pcidev() - get the pci dev from a netdev * @netdev: the netdev that pci dev will be retrived from * * Returns: NULL or the corrsponding pci_dev - **/ + */ struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev) { if (!netdev->dev.parent) @@ -54,16 +54,14 @@ struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev) } /** - * fcoe_transport_device_lookup - find out netdev is managed by the - * transport - * assign a transport to a device + * fcoe_transport_device_lookup() - Lookup a transport * @netdev: the netdev the transport to be attached to * * This will look for existing offload driver, if not found, it falls back to * the default sw hba (fcoe_sw) as its fcoe transport. * * Returns: 0 for success - **/ + */ static struct fcoe_transport_internal *fcoe_transport_device_lookup( struct fcoe_transport *t, struct net_device *netdev) { @@ -81,14 +79,14 @@ static struct fcoe_transport_internal *fcoe_transport_device_lookup( return NULL; } /** - * fcoe_transport_device_add - assign a transport to a device + * fcoe_transport_device_add() - Assign a transport to a device * @netdev: the netdev the transport to be attached to * * This will look for existing offload driver, if not found, it falls back to * the default sw hba (fcoe_sw) as its fcoe transport. * * Returns: 0 for success - **/ + */ static int fcoe_transport_device_add(struct fcoe_transport *t, struct net_device *netdev) { @@ -123,14 +121,14 @@ static int fcoe_transport_device_add(struct fcoe_transport *t, } /** - * fcoe_transport_device_remove - remove a device from its transport + * fcoe_transport_device_remove() - Remove a device from its transport * @netdev: the netdev the transport to be attached to * - * this removes the device from the transport so the given transport will + * This removes the device from the transport so the given transport will * not manage this device any more * * Returns: 0 for success - **/ + */ static int fcoe_transport_device_remove(struct fcoe_transport *t, struct net_device *netdev) { @@ -155,13 +153,13 @@ static int fcoe_transport_device_remove(struct fcoe_transport *t, } /** - * fcoe_transport_device_remove_all - remove all from transport devlist + * fcoe_transport_device_remove_all() - Remove all from transport devlist * - * this removes the device from the transport so the given transport will + * This removes the device from the transport so the given transport will * not manage this device any more * * Returns: 0 for success - **/ + */ static void fcoe_transport_device_remove_all(struct fcoe_transport *t) { struct fcoe_transport_internal *ti, *tmp; @@ -175,16 +173,16 @@ static void fcoe_transport_device_remove_all(struct fcoe_transport *t) } /** - * fcoe_transport_match - use the bus device match function to match the hw - * @t: the fcoe transport - * @netdev: + * fcoe_transport_match() - Use the bus device match function to match the hw + * @t: The fcoe transport to check + * @netdev: The netdev to match against * - * This function is used to check if the givne transport wants to manage the + * This function is used to check if the given transport wants to manage the * input netdev. if the transports implements the match function, it will be * called, o.w. we just compare the pci vendor and device id. * * Returns: true for match up - **/ + */ static bool fcoe_transport_match(struct fcoe_transport *t, struct net_device *netdev) { @@ -210,15 +208,15 @@ static bool fcoe_transport_match(struct fcoe_transport *t, } /** - * fcoe_transport_lookup - check if the transport is already registered + * fcoe_transport_lookup() - Check if the transport is already registered * @t: the transport to be looked up * * This compares the parent device (pci) vendor and device id * * Returns: NULL if not found * - * TODO - return default sw transport if no other transport is found - **/ + * TODO: return default sw transport if no other transport is found + */ static struct fcoe_transport *fcoe_transport_lookup( struct net_device *netdev) { @@ -239,11 +237,11 @@ static struct fcoe_transport *fcoe_transport_lookup( } /** - * fcoe_transport_register - adds a fcoe transport to the fcoe transports list + * fcoe_transport_register() - Adds a fcoe transport to the fcoe transports list * @t: ptr to the fcoe transport to be added * * Returns: 0 for success - **/ + */ int fcoe_transport_register(struct fcoe_transport *t) { struct fcoe_transport *tt; @@ -269,11 +267,11 @@ int fcoe_transport_register(struct fcoe_transport *t) EXPORT_SYMBOL_GPL(fcoe_transport_register); /** - * fcoe_transport_unregister - remove the tranport fro the fcoe transports list + * fcoe_transport_unregister() - Remove the tranport fro the fcoe transports list * @t: ptr to the fcoe transport to be removed * * Returns: 0 for success - **/ + */ int fcoe_transport_unregister(struct fcoe_transport *t) { struct fcoe_transport *tt, *tmp; @@ -294,8 +292,8 @@ int fcoe_transport_unregister(struct fcoe_transport *t) } EXPORT_SYMBOL_GPL(fcoe_transport_unregister); -/* - * fcoe_load_transport_driver - load an offload driver by alias name +/** + * fcoe_load_transport_driver() - Load an offload driver by alias name * @netdev: the target net device * * Requests for an offload driver module as the fcoe transport, if fails, it @@ -307,7 +305,7 @@ EXPORT_SYMBOL_GPL(fcoe_transport_unregister); * 3. pure hw fcoe hba may not have netdev * * Returns: 0 for success - **/ + */ int fcoe_load_transport_driver(struct net_device *netdev) { struct pci_dev *pci; @@ -335,14 +333,14 @@ int fcoe_load_transport_driver(struct net_device *netdev) EXPORT_SYMBOL_GPL(fcoe_load_transport_driver); /** - * fcoe_transport_attach - load transport to fcoe + * fcoe_transport_attach() - Load transport to fcoe * @netdev: the netdev the transport to be attached to * * This will look for existing offload driver, if not found, it falls back to * the default sw hba (fcoe_sw) as its fcoe transport. * * Returns: 0 for success - **/ + */ int fcoe_transport_attach(struct net_device *netdev) { struct fcoe_transport *t; @@ -373,11 +371,11 @@ int fcoe_transport_attach(struct net_device *netdev) EXPORT_SYMBOL_GPL(fcoe_transport_attach); /** - * fcoe_transport_release - unload transport from fcoe + * fcoe_transport_release() - Unload transport from fcoe * @netdev: the net device on which fcoe is to be released * * Returns: 0 for success - **/ + */ int fcoe_transport_release(struct net_device *netdev) { struct fcoe_transport *t; @@ -410,12 +408,12 @@ int fcoe_transport_release(struct net_device *netdev) EXPORT_SYMBOL_GPL(fcoe_transport_release); /** - * fcoe_transport_init - initializes fcoe transport layer + * fcoe_transport_init() - Initializes fcoe transport layer * * This prepares for the fcoe transport layer * * Returns: none - **/ + */ int __init fcoe_transport_init(void) { INIT_LIST_HEAD(&fcoe_transports); @@ -424,12 +422,13 @@ int __init fcoe_transport_init(void) } /** - * fcoe_transport_exit - cleans up the fcoe transport layer + * fcoe_transport_exit() - Cleans up the fcoe transport layer + * * This cleans up the fcoe transport layer. removing any transport on the list, * note that the transport destroy func is not called here. * * Returns: none - **/ + */ int __exit fcoe_transport_exit(void) { struct fcoe_transport *t, *tmp; diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index cf83675a0fb9..007d1fbae808 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -104,13 +104,12 @@ static struct scsi_host_template fcoe_sw_shost_template = { .max_sectors = 0xffff, }; -/* - * fcoe_sw_lport_config - sets up the fc_lport +/** + * fcoe_sw_lport_config() - sets up the fc_lport * @lp: ptr to the fc_lport * @shost: ptr to the parent scsi host * * Returns: 0 for success - * */ static int fcoe_sw_lport_config(struct fc_lport *lp) { @@ -137,16 +136,14 @@ static int fcoe_sw_lport_config(struct fc_lport *lp) return 0; } -/* - * fcoe_sw_netdev_config - sets up fcoe_softc for lport and network - * related properties +/** + * fcoe_sw_netdev_config() - Set up netdev for SW FCoE * @lp : ptr to the fc_lport * @netdev : ptr to the associated netdevice struct * * Must be called after fcoe_sw_lport_config() as it will use lport mutex * * Returns : 0 for success - * */ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) { @@ -224,16 +221,15 @@ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) return 0; } -/* - * fcoe_sw_shost_config - sets up fc_lport->host +/** + * fcoe_sw_shost_config() - Sets up fc_lport->host * @lp : ptr to the fc_lport * @shost : ptr to the associated scsi host * @dev : device associated to scsi host * - * Must be called after fcoe_sw_lport_config) and fcoe_sw_netdev_config() + * Must be called after fcoe_sw_lport_config() and fcoe_sw_netdev_config() * * Returns : 0 for success - * */ static int fcoe_sw_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, struct device *dev) @@ -261,8 +257,8 @@ static int fcoe_sw_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, return 0; } -/* - * fcoe_sw_em_config - allocates em for this lport +/** + * fcoe_sw_em_config() - allocates em for this lport * @lp: the port that em is to allocated for * * Returns : 0 on success @@ -279,8 +275,8 @@ static inline int fcoe_sw_em_config(struct fc_lport *lp) return 0; } -/* - * fcoe_sw_destroy - FCoE software HBA tear-down function +/** + * fcoe_sw_destroy() - FCoE software HBA tear-down function * @netdev: ptr to the associated net_device * * Returns: 0 if link is OK for use by FCoE. @@ -353,8 +349,8 @@ static struct libfc_function_template fcoe_sw_libfc_fcn_templ = { .frame_send = fcoe_xmit, }; -/* - * fcoe_sw_create - this function creates the fcoe interface +/** + * fcoe_sw_create() - this function creates the fcoe interface * @netdev: pointer the associated netdevice * * Creates fc_lport struct and scsi_host for lport, configures lport @@ -440,8 +436,8 @@ out_host_put: return rc; } -/* - * fcoe_sw_match - the fcoe sw transport match function +/** + * fcoe_sw_match() - The FCoE SW transport match function * * Returns : false always */ @@ -461,8 +457,8 @@ struct fcoe_transport fcoe_sw_transport = { .device = 0xffff, }; -/* - * fcoe_sw_init - registers fcoe_sw_transport +/** + * fcoe_sw_init() - Registers fcoe_sw_transport * * Returns : 0 on success */ @@ -480,8 +476,8 @@ int __init fcoe_sw_init(void) return 0; } -/* - * fcoe_sw_exit - unregisters fcoe_sw_transport +/** + * fcoe_sw_exit() - Unregisters fcoe_sw_transport * * Returns : 0 on success */ diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 296071043f55..5e68652985b2 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -91,13 +91,13 @@ static struct notifier_block fcoe_cpu_notifier = { }; /** - * fcoe_create_percpu_data - creates the associated cpu data + * fcoe_create_percpu_data() - creates the associated cpu data * @cpu: index for the cpu where fcoe cpu data will be created * * create percpu stats block, from cpu add notifier * * Returns: none - **/ + */ static void fcoe_create_percpu_data(int cpu) { struct fc_lport *lp; @@ -115,13 +115,13 @@ static void fcoe_create_percpu_data(int cpu) } /** - * fcoe_destroy_percpu_data - destroys the associated cpu data + * fcoe_destroy_percpu_data() - destroys the associated cpu data * @cpu: index for the cpu where fcoe cpu data will destroyed * * destroy percpu stats block called by cpu add/remove notifier * * Retuns: none - **/ + */ static void fcoe_destroy_percpu_data(int cpu) { struct fc_lport *lp; @@ -137,7 +137,7 @@ static void fcoe_destroy_percpu_data(int cpu) } /** - * fcoe_cpu_callback - fcoe cpu hotplug event callback + * fcoe_cpu_callback() - fcoe cpu hotplug event callback * @nfb: callback data block * @action: event triggering the callback * @hcpu: index for the cpu of this event @@ -145,7 +145,7 @@ static void fcoe_destroy_percpu_data(int cpu) * this creates or destroys per cpu data for fcoe * * Returns NOTIFY_OK always. - **/ + */ static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -166,7 +166,7 @@ static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action, #endif /* CONFIG_HOTPLUG_CPU */ /** - * fcoe_rcv - this is the fcoe receive function called by NET_RX_SOFTIRQ + * fcoe_rcv() - this is the fcoe receive function called by NET_RX_SOFTIRQ * @skb: the receive skb * @dev: associated net device * @ptype: context @@ -175,7 +175,7 @@ static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action, * this function will receive the packet and build fc frame and pass it up * * Returns: 0 for success - **/ + */ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *olddev) { @@ -265,11 +265,11 @@ err2: EXPORT_SYMBOL_GPL(fcoe_rcv); /** - * fcoe_start_io - pass to netdev to start xmit for fcoe + * fcoe_start_io() - pass to netdev to start xmit for fcoe * @skb: the skb to be xmitted * * Returns: 0 for success - **/ + */ static inline int fcoe_start_io(struct sk_buff *skb) { int rc; @@ -283,12 +283,12 @@ static inline int fcoe_start_io(struct sk_buff *skb) } /** - * fcoe_get_paged_crc_eof - in case we need alloc a page for crc_eof + * fcoe_get_paged_crc_eof() - in case we need alloc a page for crc_eof * @skb: the skb to be xmitted * @tlen: total len * * Returns: 0 for success - **/ + */ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) { struct fcoe_percpu_s *fps; @@ -326,13 +326,12 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) } /** - * fcoe_fc_crc - calculates FC CRC in this fcoe skb + * fcoe_fc_crc() - calculates FC CRC in this fcoe skb * @fp: the fc_frame containg data to be checksummed * * This uses crc32() to calculate the crc for fc frame * Return : 32 bit crc - * - **/ + */ u32 fcoe_fc_crc(struct fc_frame *fp) { struct sk_buff *skb = fp_skb(fp); @@ -363,13 +362,12 @@ u32 fcoe_fc_crc(struct fc_frame *fp) EXPORT_SYMBOL_GPL(fcoe_fc_crc); /** - * fcoe_xmit - FCoE frame transmit function + * fcoe_xmit() - FCoE frame transmit function * @lp: the associated local port * @fp: the fc_frame to be transmitted * * Return : 0 for success - * - **/ + */ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) { int wlen, rc = 0; @@ -511,12 +509,11 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) } EXPORT_SYMBOL_GPL(fcoe_xmit); -/* - * fcoe_percpu_receive_thread - recv thread per cpu +/** + * fcoe_percpu_receive_thread() - recv thread per cpu * @arg: ptr to the fcoe per cpu struct * * Return: 0 for success - * */ int fcoe_percpu_receive_thread(void *arg) { @@ -658,7 +655,7 @@ int fcoe_percpu_receive_thread(void *arg) } /** - * fcoe_recv_flogi - flogi receive function + * fcoe_recv_flogi() - flogi receive function * @fc: associated fcoe_softc * @fp: the recieved frame * @sa: the source address of this flogi @@ -667,7 +664,7 @@ int fcoe_percpu_receive_thread(void *arg) * mac address for the initiator, eitehr OUI based or GW based. * * Returns: none - **/ + */ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) { struct fc_frame_header *fh; @@ -715,7 +712,7 @@ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) } /** - * fcoe_watchdog - fcoe timer callback + * fcoe_watchdog() - fcoe timer callback * @vp: * * This checks the pending queue length for fcoe and set lport qfull @@ -723,7 +720,7 @@ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) * fcoe_hostlist. * * Returns: 0 for success - **/ + */ void fcoe_watchdog(ulong vp) { struct fc_lport *lp; @@ -750,7 +747,7 @@ void fcoe_watchdog(ulong vp) /** - * fcoe_check_wait_queue - put the skb into fcoe pending xmit queue + * fcoe_check_wait_queue() - put the skb into fcoe pending xmit queue * @lp: the fc_port for this skb * @skb: the associated skb to be xmitted * @@ -764,7 +761,7 @@ void fcoe_watchdog(ulong vp) * by the next skb transmit. * * Returns: 0 for success - **/ + */ static int fcoe_check_wait_queue(struct fc_lport *lp) { int rc; @@ -797,12 +794,12 @@ static int fcoe_check_wait_queue(struct fc_lport *lp) } /** - * fcoe_insert_wait_queue_head - puts skb to fcoe pending queue head + * fcoe_insert_wait_queue_head() - puts skb to fcoe pending queue head * @lp: the fc_port for this skb * @skb: the associated skb to be xmitted * * Returns: none - **/ + */ static void fcoe_insert_wait_queue_head(struct fc_lport *lp, struct sk_buff *skb) { @@ -815,12 +812,12 @@ static void fcoe_insert_wait_queue_head(struct fc_lport *lp, } /** - * fcoe_insert_wait_queue - put the skb into fcoe pending queue tail + * fcoe_insert_wait_queue() - put the skb into fcoe pending queue tail * @lp: the fc_port for this skb * @skb: the associated skb to be xmitted * * Returns: none - **/ + */ static void fcoe_insert_wait_queue(struct fc_lport *lp, struct sk_buff *skb) { @@ -833,10 +830,9 @@ static void fcoe_insert_wait_queue(struct fc_lport *lp, } /** - * fcoe_dev_setup - setup link change notification interface - * - **/ -static void fcoe_dev_setup(void) + * fcoe_dev_setup() - setup link change notification interface + */ +static void fcoe_dev_setup() { /* * here setup a interface specific wd time to @@ -846,15 +842,15 @@ static void fcoe_dev_setup(void) } /** - * fcoe_dev_setup - cleanup link change notification interface - **/ + * fcoe_dev_setup() - cleanup link change notification interface + */ static void fcoe_dev_cleanup(void) { unregister_netdevice_notifier(&fcoe_notifier); } /** - * fcoe_device_notification - netdev event notification callback + * fcoe_device_notification() - netdev event notification callback * @notifier: context of the notification * @event: type of event * @ptr: fixed array for output parsed ifname @@ -862,7 +858,7 @@ static void fcoe_dev_cleanup(void) * This function is called by the ethernet driver in case of link change event * * Returns: 0 for success - **/ + */ static int fcoe_device_notification(struct notifier_block *notifier, ulong event, void *ptr) { @@ -926,12 +922,12 @@ out: } /** - * fcoe_if_to_netdev - parse a name buffer to get netdev + * fcoe_if_to_netdev() - parse a name buffer to get netdev * @ifname: fixed array for output parsed ifname * @buffer: incoming buffer to be copied * * Returns: NULL or ptr to netdeive - **/ + */ static struct net_device *fcoe_if_to_netdev(const char *buffer) { char *cp; @@ -948,11 +944,11 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer) } /** - * fcoe_netdev_to_module_owner - finds out the nic drive moddule of the netdev + * fcoe_netdev_to_module_owner() - finds out the nic drive moddule of the netdev * @netdev: the target netdev * * Returns: ptr to the struct module, NULL for failure - **/ + */ static struct module *fcoe_netdev_to_module_owner( const struct net_device *netdev) { @@ -972,12 +968,14 @@ static struct module *fcoe_netdev_to_module_owner( } /** - * fcoe_ethdrv_get - holds the nic driver module by try_module_get() for - * the corresponding netdev. + * fcoe_ethdrv_get() - Hold the Ethernet driver * @netdev: the target netdev * + * Holds the Ethernet driver module by try_module_get() for + * the corresponding netdev. + * * Returns: 0 for succsss - **/ + */ static int fcoe_ethdrv_get(const struct net_device *netdev) { struct module *owner; @@ -992,12 +990,14 @@ static int fcoe_ethdrv_get(const struct net_device *netdev) } /** - * fcoe_ethdrv_get - releases the nic driver module by module_put for - * the corresponding netdev. + * fcoe_ethdrv_put() - Release the Ethernet driver * @netdev: the target netdev * + * Releases the Ethernet driver module by module_put for + * the corresponding netdev. + * * Returns: 0 for succsss - **/ + */ static int fcoe_ethdrv_put(const struct net_device *netdev) { struct module *owner; @@ -1013,12 +1013,12 @@ static int fcoe_ethdrv_put(const struct net_device *netdev) } /** - * fcoe_destroy- handles the destroy from sysfs + * fcoe_destroy() - handles the destroy from sysfs * @buffer: expcted to be a eth if name * @kp: associated kernel param * * Returns: 0 for success - **/ + */ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) { int rc; @@ -1051,12 +1051,12 @@ out_nodev: } /** - * fcoe_create - handles the create call from sysfs + * fcoe_create() - Handles the create call from sysfs * @buffer: expcted to be a eth if name * @kp: associated kernel param * * Returns: 0 for success - **/ + */ static int fcoe_create(const char *buffer, struct kernel_param *kp) { int rc; @@ -1097,8 +1097,8 @@ module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR); __MODULE_PARM_TYPE(destroy, "string"); MODULE_PARM_DESC(destroy, "Destroy fcoe port"); -/* - * fcoe_link_ok - check if link is ok for the fc_lport +/** + * fcoe_link_ok() - Check if link is ok for the fc_lport * @lp: ptr to the fc_lport * * Any permanently-disqualifying conditions have been previously checked. @@ -1142,9 +1142,8 @@ int fcoe_link_ok(struct fc_lport *lp) } EXPORT_SYMBOL_GPL(fcoe_link_ok); -/* - * fcoe_percpu_clean - frees skb of the corresponding lport from the per - * cpu queue. +/** + * fcoe_percpu_clean() - Clear the pending skbs for an lport * @lp: the fc_lport */ void fcoe_percpu_clean(struct fc_lport *lp) @@ -1178,11 +1177,11 @@ void fcoe_percpu_clean(struct fc_lport *lp) EXPORT_SYMBOL_GPL(fcoe_percpu_clean); /** - * fcoe_clean_pending_queue - dequeue skb and free it + * fcoe_clean_pending_queue() - Dequeue a skb and free it * @lp: the corresponding fc_lport * * Returns: none - **/ + */ void fcoe_clean_pending_queue(struct fc_lport *lp) { struct fcoe_softc *fc = lport_priv(lp); @@ -1199,12 +1198,12 @@ void fcoe_clean_pending_queue(struct fc_lport *lp) EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue); /** - * libfc_host_alloc - allocate a Scsi_Host with room for the fc_lport + * libfc_host_alloc() - Allocate a Scsi_Host with room for the fc_lport * @sht: ptr to the scsi host templ * @priv_size: size of private data after fc_lport * * Returns: ptr to Scsi_Host - * TODO - to libfc? + * TODO: to libfc? */ static inline struct Scsi_Host *libfc_host_alloc( struct scsi_host_template *sht, int priv_size) @@ -1213,7 +1212,7 @@ static inline struct Scsi_Host *libfc_host_alloc( } /** - * fcoe_host_alloc - allocate a Scsi_Host with room for the fcoe_softc + * fcoe_host_alloc() - Allocate a Scsi_Host with room for the fcoe_softc * @sht: ptr to the scsi host templ * @priv_size: size of private data after fc_lport * @@ -1225,8 +1224,8 @@ struct Scsi_Host *fcoe_host_alloc(struct scsi_host_template *sht, int priv_size) } EXPORT_SYMBOL_GPL(fcoe_host_alloc); -/* - * fcoe_reset - resets the fcoe +/** + * fcoe_reset() - Resets the fcoe * @shost: shost the reset is from * * Returns: always 0 @@ -1239,8 +1238,8 @@ int fcoe_reset(struct Scsi_Host *shost) } EXPORT_SYMBOL_GPL(fcoe_reset); -/* - * fcoe_wwn_from_mac - converts 48-bit IEEE MAC address to 64-bit FC WWN. +/** + * fcoe_wwn_from_mac() - Converts 48-bit IEEE MAC address to 64-bit FC WWN. * @mac: mac address * @scheme: check port * @port: port indicator for converting @@ -1279,8 +1278,9 @@ u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN], return wwn; } EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac); -/* - * fcoe_hostlist_lookup_softc - find the corresponding lport by a given device + +/** + * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device * @device: this is currently ptr to net_device * * Returns: NULL or the located fcoe_softc @@ -1301,8 +1301,8 @@ static struct fcoe_softc *fcoe_hostlist_lookup_softc( return NULL; } -/* - * fcoe_hostlist_lookup - find the corresponding lport by netdev +/** + * fcoe_hostlist_lookup() - Find the corresponding lport by netdev * @netdev: ptr to net_device * * Returns: 0 for success @@ -1317,8 +1317,8 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) } EXPORT_SYMBOL_GPL(fcoe_hostlist_lookup); -/* - * fcoe_hostlist_add - add a lport to lports list +/** + * fcoe_hostlist_add() - Add a lport to lports list * @lp: ptr to the fc_lport to badded * * Returns: 0 for success @@ -1338,8 +1338,8 @@ int fcoe_hostlist_add(const struct fc_lport *lp) } EXPORT_SYMBOL_GPL(fcoe_hostlist_add); -/* - * fcoe_hostlist_remove - remove a lport from lports list +/** + * fcoe_hostlist_remove() - remove a lport from lports list * @lp: ptr to the fc_lport to badded * * Returns: 0 for success @@ -1359,12 +1359,12 @@ int fcoe_hostlist_remove(const struct fc_lport *lp) EXPORT_SYMBOL_GPL(fcoe_hostlist_remove); /** - * fcoe_libfc_config - sets up libfc related properties for lport + * fcoe_libfc_config() - sets up libfc related properties for lport * @lp: ptr to the fc_lport * @tt: libfc function template * * Returns : 0 for success - **/ + */ int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt) { /* Set the function pointers set by the LLDD */ @@ -1382,14 +1382,14 @@ int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt) EXPORT_SYMBOL_GPL(fcoe_libfc_config); /** - * fcoe_init - fcoe module loading initialization + * fcoe_init() - fcoe module loading initialization * * Initialization routine * 1. Will create fc transport software structure * 2. initialize the link list of port information structure * * Returns 0 on success, negative on failure - **/ + */ static int __init fcoe_init(void) { int cpu; @@ -1452,10 +1452,10 @@ static int __init fcoe_init(void) module_init(fcoe_init); /** - * fcoe_exit - fcoe module unloading cleanup + * fcoe_exit() - fcoe module unloading cleanup * * Returns 0 on success, negative on failure - **/ + */ static void __exit fcoe_exit(void) { u32 idx; diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index cfbce893941a..e57556ea5b48 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -64,7 +64,7 @@ static void fc_disc_single(struct fc_disc *, struct fc_disc_port *); static void fc_disc_restart(struct fc_disc *); /** - * fc_disc_lookup_rport - lookup a remote port by port_id + * fc_disc_lookup_rport() - lookup a remote port by port_id * @lport: Fibre Channel host port instance * @port_id: remote port port_id to match */ @@ -92,7 +92,7 @@ struct fc_rport *fc_disc_lookup_rport(const struct fc_lport *lport, } /** - * fc_disc_stop_rports - delete all the remote ports associated with the lport + * fc_disc_stop_rports() - delete all the remote ports associated with the lport * @disc: The discovery job to stop rports on * * Locking Note: This function expects that the lport mutex is locked before @@ -117,7 +117,7 @@ void fc_disc_stop_rports(struct fc_disc *disc) } /** - * fc_disc_rport_callback - Event handler for rport events + * fc_disc_rport_callback() - Event handler for rport events * @lport: The lport which is receiving the event * @rport: The rport which the event has occured on * @event: The event that occured @@ -151,7 +151,7 @@ static void fc_disc_rport_callback(struct fc_lport *lport, } /** - * fc_disc_recv_rscn_req - Handle Registered State Change Notification (RSCN) + * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN) * @sp: Current sequence of the RSCN exchange * @fp: RSCN Frame * @lport: Fibre Channel host port instance @@ -265,7 +265,7 @@ reject: } /** - * fc_disc_recv_req - Handle incoming requests + * fc_disc_recv_req() - Handle incoming requests * @sp: Current sequence of the request exchange * @fp: The frame * @lport: The FC local port @@ -294,7 +294,7 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_disc_restart - Restart discovery + * fc_disc_restart() - Restart discovery * @lport: FC discovery context * * Locking Note: This function expects that the disc mutex @@ -322,7 +322,7 @@ static void fc_disc_restart(struct fc_disc *disc) } /** - * fc_disc_start - Fibre Channel Target discovery + * fc_disc_start() - Fibre Channel Target discovery * @lport: FC local port * * Returns non-zero if discovery cannot be started. @@ -383,7 +383,7 @@ static struct fc_rport_operations fc_disc_rport_ops = { }; /** - * fc_disc_new_target - Handle new target found by discovery + * fc_disc_new_target() - Handle new target found by discovery * @lport: FC local port * @rport: The previous FC remote port (NULL if new remote port) * @ids: Identifiers for the new FC remote port @@ -446,7 +446,7 @@ static int fc_disc_new_target(struct fc_disc *disc, } /** - * fc_disc_del_target - Delete a target + * fc_disc_del_target() - Delete a target * @disc: FC discovery context * @rport: The remote port to be removed */ @@ -459,7 +459,7 @@ static void fc_disc_del_target(struct fc_disc *disc, struct fc_rport *rport) } /** - * fc_disc_done - Discovery has been completed + * fc_disc_done() - Discovery has been completed * @disc: FC discovery context */ static void fc_disc_done(struct fc_disc *disc) @@ -479,7 +479,7 @@ static void fc_disc_done(struct fc_disc *disc) } /** - * fc_disc_error - Handle error on dNS request + * fc_disc_error() - Handle error on dNS request * @disc: FC discovery context * @fp: The frame pointer */ @@ -519,7 +519,7 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp) } /** - * fc_disc_gpn_ft_req - Send Get Port Names by FC-4 type (GPN_FT) request + * fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request * @lport: FC discovery context * * Locking Note: This function expects that the disc_mutex is locked @@ -553,7 +553,7 @@ err: } /** - * fc_disc_gpn_ft_parse - Parse the list of IDs and names resulting from a request + * fc_disc_gpn_ft_parse() - Parse the list of IDs and names resulting from a request * @lport: Fibre Channel host port instance * @buf: GPN_FT response buffer * @len: size of response buffer @@ -658,7 +658,10 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) return error; } -/* +/** + * fc_disc_timeout() - Retry handler for the disc component + * @work: Structure holding disc obj that needs retry discovery + * * Handle retry of memory allocation for remote ports. */ static void fc_disc_timeout(struct work_struct *work) @@ -673,7 +676,7 @@ static void fc_disc_timeout(struct work_struct *work) } /** - * fc_disc_gpn_ft_resp - Handle a response frame from Get Port Names (GPN_FT) + * fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT) * @sp: Current sequence of GPN_FT exchange * @fp: response frame * @lp_arg: Fibre Channel host port instance @@ -712,9 +715,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, fr_len(fp)); } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) { - /* - * Accepted. Parse response. - */ + /* Accepted, parse the response. */ buf = cp + 1; len -= sizeof(*cp); } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { @@ -746,7 +747,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_disc_single - Discover the directory information for a single target + * fc_disc_single() - Discover the directory information for a single target * @lport: FC local port * @dp: The port to rediscover * @@ -782,7 +783,7 @@ out: } /** - * fc_disc_stop - Stop discovery for a given lport + * fc_disc_stop() - Stop discovery for a given lport * @lport: The lport that discovery should stop for */ void fc_disc_stop(struct fc_lport *lport) @@ -796,7 +797,7 @@ void fc_disc_stop(struct fc_lport *lport) } /** - * fc_disc_stop_final - Stop discovery for a given lport + * fc_disc_stop_final() - Stop discovery for a given lport * @lport: The lport that discovery should stop for * * This function will block until discovery has been @@ -809,7 +810,7 @@ void fc_disc_stop_final(struct fc_lport *lport) } /** - * fc_disc_init - Initialize the discovery block + * fc_disc_init() - Initialize the discovery block * @lport: FC local port */ int fc_disc_init(struct fc_lport *lport) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index ecc72612c385..2a631d7dbcec 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -161,7 +161,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lp, gfp_t gfp) } /** - * fc_fcp_pkt_release - release hold on scsi_pkt packet + * fc_fcp_pkt_release() - release hold on scsi_pkt packet * @fsp: fcp packet struct * * This is used by upper layer scsi driver. @@ -183,8 +183,7 @@ static void fc_fcp_pkt_hold(struct fc_fcp_pkt *fsp) } /** - * fc_fcp_pkt_destory - release hold on scsi_pkt packet - * + * fc_fcp_pkt_destory() - release hold on scsi_pkt packet * @seq: exchange sequence * @fsp: fcp packet struct * @@ -199,7 +198,7 @@ static void fc_fcp_pkt_destroy(struct fc_seq *seq, void *fsp) } /** - * fc_fcp_lock_pkt - lock a packet and get a ref to it. + * fc_fcp_lock_pkt() - lock a packet and get a ref to it. * @fsp: fcp packet * * We should only return error if we return a command to scsi-ml before @@ -291,9 +290,7 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) buf = fc_frame_payload_get(fp, 0); if (offset + len > fsp->data_len) { - /* - * this should never happen - */ + /* this should never happen */ if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) && fc_frame_crc_check(fp)) goto crc_err; @@ -387,8 +384,8 @@ crc_err: fc_fcp_complete_locked(fsp); } -/* - * fc_fcp_send_data - Send SCSI data to target. +/** + * fc_fcp_send_data() - Send SCSI data to target. * @fsp: ptr to fc_fcp_pkt * @sp: ptr to this sequence * @offset: starting offset for this data request @@ -610,8 +607,8 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) } } -/* - * fc_fcp_reduce_can_queue - drop can_queue +/** + * fc_fcp_reduce_can_queue() - drop can_queue * @lp: lport to drop queueing for * * If we are getting memory allocation failures, then we may @@ -642,9 +639,11 @@ done: spin_unlock_irqrestore(lp->host->host_lock, flags); } -/* - * exch mgr calls this routine to process scsi - * exchanges. +/** + * fc_fcp_recv() - Reveive FCP frames + * @seq: The sequence the frame is on + * @fp: The FC frame + * @arg: The related FCP packet * * Return : None * Context : called from Soft IRQ context @@ -832,7 +831,7 @@ err: } /** - * fc_fcp_complete_locked - complete processing of a fcp packet + * fc_fcp_complete_locked() - complete processing of a fcp packet * @fsp: fcp packet * * This function may sleep if a timer is pending. The packet lock must be @@ -900,7 +899,7 @@ static void fc_fcp_cleanup_cmd(struct fc_fcp_pkt *fsp, int error) } /** - * fc_fcp_cleanup_each_cmd - run fn on each active command + * fc_fcp_cleanup_each_cmd() - Cleanup active commads * @lp: logical port * @id: target id * @lun: lun @@ -952,7 +951,7 @@ static void fc_fcp_abort_io(struct fc_lport *lp) } /** - * fc_fcp_pkt_send - send a fcp packet to the lower level. + * fc_fcp_pkt_send() - send a fcp packet to the lower level. * @lp: fc lport * @fsp: fc packet. * @@ -1727,7 +1726,7 @@ out: EXPORT_SYMBOL(fc_queuecommand); /** - * fc_io_compl - Handle responses for completed commands + * fc_io_compl() - Handle responses for completed commands * @fsp: scsi packet * * Translates a error to a Linux SCSI error. @@ -1857,7 +1856,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) } /** - * fc_fcp_complete - complete processing of a fcp packet + * fc_fcp_complete() - complete processing of a fcp packet * @fsp: fcp packet * * This function may sleep if a fsp timer is pending. @@ -1874,9 +1873,10 @@ void fc_fcp_complete(struct fc_fcp_pkt *fsp) EXPORT_SYMBOL(fc_fcp_complete); /** - * fc_eh_abort - Abort a command...from scsi host template + * fc_eh_abort() - Abort a command * @sc_cmd: scsi command to abort * + * From scsi host template. * send ABTS to the target device and wait for the response * sc_cmd is the pointer to the command to be aborted. */ @@ -1920,7 +1920,7 @@ release_pkt: EXPORT_SYMBOL(fc_eh_abort); /** - * fc_eh_device_reset: Reset a single LUN + * fc_eh_device_reset() Reset a single LUN * @sc_cmd: scsi command * * Set from scsi host template to send tm cmd to the target and wait for the @@ -1973,7 +1973,7 @@ out: EXPORT_SYMBOL(fc_eh_device_reset); /** - * fc_eh_host_reset - The reset function will reset the ports on the host. + * fc_eh_host_reset() - The reset function will reset the ports on the host. * @sc_cmd: scsi command */ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) @@ -1999,7 +1999,7 @@ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) EXPORT_SYMBOL(fc_eh_host_reset); /** - * fc_slave_alloc - configure queue depth + * fc_slave_alloc() - configure queue depth * @sdev: scsi device * * Configures queue depth based on host's cmd_per_len. If not set diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index c00de2244c78..2ae50a1188e6 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -139,7 +139,7 @@ static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp) } /** - * fc_lport_rport_callback - Event handler for rport events + * fc_lport_rport_callback() - Event handler for rport events * @lport: The lport which is receiving the event * @rport: The rport which the event has occured on * @event: The event that occured @@ -195,7 +195,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport, } /** - * fc_lport_state - Return a string which represents the lport's state + * fc_lport_state() - Return a string which represents the lport's state * @lport: The lport whose state is to converted to a string */ static const char *fc_lport_state(struct fc_lport *lport) @@ -209,7 +209,7 @@ static const char *fc_lport_state(struct fc_lport *lport) } /** - * fc_lport_ptp_setup - Create an rport for point-to-point mode + * fc_lport_ptp_setup() - Create an rport for point-to-point mode * @lport: The lport to attach the ptp rport to * @fid: The FID of the ptp rport * @remote_wwpn: The WWPN of the ptp rport @@ -351,7 +351,7 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type) } /** - * fc_lport_recv_rlir_req - Handle received Registered Link Incident Report. + * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report. * @lport: Fibre Channel local port recieving the RLIR * @sp: current sequence in the RLIR exchange * @fp: RLIR request frame @@ -370,7 +370,7 @@ static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_lport_recv_echo_req - Handle received ECHO request + * fc_lport_recv_echo_req() - Handle received ECHO request * @lport: Fibre Channel local port recieving the ECHO * @sp: current sequence in the ECHO exchange * @fp: ECHO request frame @@ -412,7 +412,7 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, } /** - * fc_lport_recv_echo_req - Handle received Request Node ID data request + * fc_lport_recv_echo_req() - Handle received Request Node ID data request * @lport: Fibre Channel local port recieving the RNID * @sp: current sequence in the RNID exchange * @fp: RNID request frame @@ -479,7 +479,7 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, } /** - * fc_lport_recv_adisc_req - Handle received Address Discovery Request + * fc_lport_recv_adisc_req() - Handle received Address Discovery Request * @lport: Fibre Channel local port recieving the ADISC * @sp: current sequence in the ADISC exchange * @fp: ADISC request frame @@ -529,7 +529,7 @@ static void fc_lport_recv_adisc_req(struct fc_seq *sp, struct fc_frame *in_fp, } /** - * fc_lport_recv_logo_req - Handle received fabric LOGO request + * fc_lport_recv_logo_req() - Handle received fabric LOGO request * @lport: Fibre Channel local port recieving the LOGO * @sp: current sequence in the LOGO exchange * @fp: LOGO request frame @@ -546,7 +546,7 @@ static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_fabric_login - Start the lport state machine + * fc_fabric_login() - Start the lport state machine * @lport: The lport that should log into the fabric * * Locking Note: This function should not be called @@ -568,7 +568,7 @@ int fc_fabric_login(struct fc_lport *lport) EXPORT_SYMBOL(fc_fabric_login); /** - * fc_linkup - Handler for transport linkup events + * fc_linkup() - Handler for transport linkup events * @lport: The lport whose link is up */ void fc_linkup(struct fc_lport *lport) @@ -588,7 +588,7 @@ void fc_linkup(struct fc_lport *lport) EXPORT_SYMBOL(fc_linkup); /** - * fc_linkdown - Handler for transport linkdown events + * fc_linkdown() - Handler for transport linkdown events * @lport: The lport whose link is down */ void fc_linkdown(struct fc_lport *lport) @@ -607,12 +607,12 @@ void fc_linkdown(struct fc_lport *lport) EXPORT_SYMBOL(fc_linkdown); /** - * fc_fabric_logoff - Logout of the fabric + * fc_fabric_logoff() - Logout of the fabric * @lport: fc_lport pointer to logoff the fabric * * Return value: * 0 for success, -1 for failure - **/ + */ int fc_fabric_logoff(struct fc_lport *lport) { lport->tt.disc_stop_final(lport); @@ -625,7 +625,7 @@ int fc_fabric_logoff(struct fc_lport *lport) EXPORT_SYMBOL(fc_fabric_logoff); /** - * fc_lport_destroy - unregister a fc_lport + * fc_lport_destroy() - unregister a fc_lport * @lport: fc_lport pointer to unregister * * Return value: @@ -635,7 +635,7 @@ EXPORT_SYMBOL(fc_fabric_logoff); * clean-up all the allocated memory * and free up other system resources. * - **/ + */ int fc_lport_destroy(struct fc_lport *lport) { lport->tt.frame_send = fc_frame_drop; @@ -646,15 +646,14 @@ int fc_lport_destroy(struct fc_lport *lport) EXPORT_SYMBOL(fc_lport_destroy); /** - * fc_set_mfs - sets up the mfs for the corresponding fc_lport + * fc_set_mfs() - sets up the mfs for the corresponding fc_lport * @lport: fc_lport pointer to unregister * @mfs: the new mfs for fc_lport * * Set mfs for the given fc_lport to the new mfs. * * Return: 0 for success - * - **/ + */ int fc_set_mfs(struct fc_lport *lport, u32 mfs) { unsigned int old_mfs; @@ -683,7 +682,7 @@ int fc_set_mfs(struct fc_lport *lport, u32 mfs) EXPORT_SYMBOL(fc_set_mfs); /** - * fc_lport_disc_callback - Callback for discovery events + * fc_lport_disc_callback() - Callback for discovery events * @lport: FC local port * @event: The discovery event */ @@ -708,7 +707,7 @@ void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event) } /** - * fc_rport_enter_ready - Enter the ready state and start discovery + * fc_rport_enter_ready() - Enter the ready state and start discovery * @lport: Fibre Channel local port that is ready * * Locking Note: The lport lock is expected to be held before calling @@ -725,7 +724,7 @@ static void fc_lport_enter_ready(struct fc_lport *lport) } /** - * fc_lport_recv_flogi_req - Receive a FLOGI request + * fc_lport_recv_flogi_req() - Receive a FLOGI request * @sp_in: The sequence the FLOGI is on * @rx_fp: The frame the FLOGI is in * @lport: The lport that recieved the request @@ -815,7 +814,7 @@ out: } /** - * fc_lport_recv_req - The generic lport request handler + * fc_lport_recv_req() - The generic lport request handler * @lport: The lport that received the request * @sp: The sequence the request is on * @fp: The frame the request is in @@ -911,7 +910,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, } /** - * fc_lport_reset - Reset an lport + * fc_lport_reset() - Reset an lport * @lport: The lport which should be reset * * Locking Note: This functions should not be called with the @@ -928,7 +927,7 @@ int fc_lport_reset(struct fc_lport *lport) EXPORT_SYMBOL(fc_lport_reset); /** - * fc_rport_enter_reset - Reset the local port + * fc_rport_enter_reset() - Reset the local port * @lport: Fibre Channel local port to be reset * * Locking Note: The lport lock is expected to be held before calling @@ -960,7 +959,7 @@ static void fc_lport_enter_reset(struct fc_lport *lport) } /** - * fc_lport_error - Handler for any errors + * fc_lport_error() - Handler for any errors * @lport: The fc_lport object * @fp: The frame pointer * @@ -1007,8 +1006,8 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) } /** - * fc_lport_rft_id_resp - Handle response to Register Fibre - * Channel Types by ID (RPN_ID) request + * fc_lport_rft_id_resp() - Handle response to Register Fibre + * Channel Types by ID (RPN_ID) request * @sp: current sequence in RPN_ID exchange * @fp: response frame * @lp_arg: Fibre Channel host port instance @@ -1059,8 +1058,8 @@ err: } /** - * fc_lport_rpn_id_resp - Handle response to Register Port - * Name by ID (RPN_ID) request + * fc_lport_rpn_id_resp() - Handle response to Register Port + * Name by ID (RPN_ID) request * @sp: current sequence in RPN_ID exchange * @fp: response frame * @lp_arg: Fibre Channel host port instance @@ -1111,7 +1110,7 @@ err: } /** - * fc_lport_scr_resp - Handle response to State Change Register (SCR) request + * fc_lport_scr_resp() - Handle response to State Change Register (SCR) request * @sp: current sequence in SCR exchange * @fp: response frame * @lp_arg: Fibre Channel lport port instance that sent the registration request @@ -1157,7 +1156,7 @@ err: } /** - * fc_lport_enter_scr - Send a State Change Register (SCR) request + * fc_lport_enter_scr() - Send a State Change Register (SCR) request * @lport: Fibre Channel local port to register for state changes * * Locking Note: The lport lock is expected to be held before calling @@ -1184,7 +1183,7 @@ static void fc_lport_enter_scr(struct fc_lport *lport) } /** - * fc_lport_enter_rft_id - Register FC4-types with the name server + * fc_lport_enter_rft_id() - Register FC4-types with the name server * @lport: Fibre Channel local port to register * * Locking Note: The lport lock is expected to be held before calling @@ -1226,7 +1225,7 @@ static void fc_lport_enter_rft_id(struct fc_lport *lport) } /** - * fc_rport_enter_rft_id - Register port name with the name server + * fc_rport_enter_rft_id() - Register port name with the name server * @lport: Fibre Channel local port to register * * Locking Note: The lport lock is expected to be held before calling @@ -1259,7 +1258,7 @@ static struct fc_rport_operations fc_lport_rport_ops = { }; /** - * fc_rport_enter_dns - Create a rport to the name server + * fc_rport_enter_dns() - Create a rport to the name server * @lport: Fibre Channel local port requesting a rport for the name server * * Locking Note: The lport lock is expected to be held before calling @@ -1296,7 +1295,7 @@ err: } /** - * fc_lport_timeout - Handler for the retry_work timer. + * fc_lport_timeout() - Handler for the retry_work timer. * @work: The work struct of the fc_lport */ static void fc_lport_timeout(struct work_struct *work) @@ -1337,7 +1336,7 @@ static void fc_lport_timeout(struct work_struct *work) } /** - * fc_lport_logo_resp - Handle response to LOGO request + * fc_lport_logo_resp() - Handle response to LOGO request * @sp: current sequence in LOGO exchange * @fp: response frame * @lp_arg: Fibre Channel lport port instance that sent the LOGO request @@ -1383,7 +1382,7 @@ err: } /** - * fc_rport_enter_logo - Logout of the fabric + * fc_rport_enter_logo() - Logout of the fabric * @lport: Fibre Channel local port to be logged out * * Locking Note: The lport lock is expected to be held before calling @@ -1415,7 +1414,7 @@ static void fc_lport_enter_logo(struct fc_lport *lport) } /** - * fc_lport_flogi_resp - Handle response to FLOGI request + * fc_lport_flogi_resp() - Handle response to FLOGI request * @sp: current sequence in FLOGI exchange * @fp: response frame * @lp_arg: Fibre Channel lport port instance that sent the FLOGI request @@ -1510,7 +1509,7 @@ err: } /** - * fc_rport_enter_flogi - Send a FLOGI request to the fabric manager + * fc_rport_enter_flogi() - Send a FLOGI request to the fabric manager * @lport: Fibre Channel local port to be logged in to the fabric * * Locking Note: The lport lock is expected to be held before calling diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 4f23a9bb15a1..6f07de15c491 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -146,7 +146,7 @@ struct fc_rport *fc_rport_rogue_create(struct fc_disc_port *dp) } /** - * fc_rport_state - return a string for the state the rport is in + * fc_rport_state() - return a string for the state the rport is in * @rport: The rport whose state we want to get a string for */ static const char *fc_rport_state(struct fc_rport *rport) @@ -161,7 +161,7 @@ static const char *fc_rport_state(struct fc_rport *rport) } /** - * fc_set_rport_loss_tmo - Set the remote port loss timeout in seconds. + * fc_set_rport_loss_tmo() - Set the remote port loss timeout in seconds. * @rport: Pointer to Fibre Channel remote port structure * @timeout: timeout in seconds */ @@ -175,7 +175,7 @@ void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) EXPORT_SYMBOL(fc_set_rport_loss_tmo); /** - * fc_plogi_get_maxframe - Get max payload from the common service parameters + * fc_plogi_get_maxframe() - Get max payload from the common service parameters * @flp: FLOGI payload structure * @maxval: upper limit, may be less than what is in the service parameters */ @@ -198,7 +198,7 @@ fc_plogi_get_maxframe(struct fc_els_flogi *flp, unsigned int maxval) } /** - * fc_rport_state_enter - Change the rport's state + * fc_rport_state_enter() - Change the rport's state * @rport: The rport whose state should change * @new: The new state of the rport * @@ -292,7 +292,7 @@ static void fc_rport_work(struct work_struct *work) } /** - * fc_rport_login - Start the remote port login state machine + * fc_rport_login() - Start the remote port login state machine * @rport: Fibre Channel remote port * * Locking Note: Called without the rport lock held. This @@ -315,7 +315,7 @@ int fc_rport_login(struct fc_rport *rport) } /** - * fc_rport_logoff - Logoff and remove an rport + * fc_rport_logoff() - Logoff and remove an rport * @rport: Fibre Channel remote port to be removed * * Locking Note: Called without the rport lock held. This @@ -353,7 +353,7 @@ int fc_rport_logoff(struct fc_rport *rport) } /** - * fc_rport_enter_ready - The rport is ready + * fc_rport_enter_ready() - The rport is ready * @rport: Fibre Channel remote port that is ready * * Locking Note: The rport lock is expected to be held before calling @@ -372,7 +372,7 @@ static void fc_rport_enter_ready(struct fc_rport *rport) } /** - * fc_rport_timeout - Handler for the retry_work timer. + * fc_rport_timeout() - Handler for the retry_work timer. * @work: The work struct of the fc_rport_libfc_priv * * Locking Note: Called without the rport lock held. This @@ -411,7 +411,7 @@ static void fc_rport_timeout(struct work_struct *work) } /** - * fc_rport_error - Error handler, called once retries have been exhausted + * fc_rport_error() - Error handler, called once retries have been exhausted * @rport: The fc_rport object * @fp: The frame pointer * @@ -444,7 +444,7 @@ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp) } /** - * fc_rport_error_retry - Error handler when retries are desired + * fc_rport_error_retry() - Error handler when retries are desired * @rport: The fc_rport object * @fp: The frame pointer * @@ -479,7 +479,7 @@ static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp) } /** - * fc_rport_plogi_recv_resp - Handle incoming ELS PLOGI response + * fc_rport_plogi_recv_resp() - Handle incoming ELS PLOGI response * @sp: current sequence in the PLOGI exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -554,7 +554,7 @@ err: } /** - * fc_rport_enter_plogi - Send Port Login (PLOGI) request to peer + * fc_rport_enter_plogi() - Send Port Login (PLOGI) request to peer * @rport: Fibre Channel remote port to send PLOGI to * * Locking Note: The rport lock is expected to be held before calling @@ -587,7 +587,7 @@ static void fc_rport_enter_plogi(struct fc_rport *rport) } /** - * fc_rport_prli_resp - Process Login (PRLI) response handler + * fc_rport_prli_resp() - Process Login (PRLI) response handler * @sp: current sequence in the PRLI exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -657,7 +657,7 @@ err: } /** - * fc_rport_logo_resp - Logout (LOGO) response handler + * fc_rport_logo_resp() - Logout (LOGO) response handler * @sp: current sequence in the LOGO exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -706,7 +706,7 @@ err: } /** - * fc_rport_enter_prli - Send Process Login (PRLI) request to peer + * fc_rport_enter_prli() - Send Process Login (PRLI) request to peer * @rport: Fibre Channel remote port to send PRLI to * * Locking Note: The rport lock is expected to be held before calling @@ -741,7 +741,7 @@ static void fc_rport_enter_prli(struct fc_rport *rport) } /** - * fc_rport_els_rtv_resp - Request Timeout Value response handler + * fc_rport_els_rtv_resp() - Request Timeout Value response handler * @sp: current sequence in the RTV exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -807,7 +807,7 @@ err: } /** - * fc_rport_enter_rtv - Send Request Timeout Value (RTV) request to peer + * fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request to peer * @rport: Fibre Channel remote port to send RTV to * * Locking Note: The rport lock is expected to be held before calling @@ -838,7 +838,7 @@ static void fc_rport_enter_rtv(struct fc_rport *rport) } /** - * fc_rport_enter_logo - Send Logout (LOGO) request to peer + * fc_rport_enter_logo() - Send Logout (LOGO) request to peer * @rport: Fibre Channel remote port to send LOGO to * * Locking Note: The rport lock is expected to be held before calling @@ -870,7 +870,7 @@ static void fc_rport_enter_logo(struct fc_rport *rport) /** - * fc_rport_recv_req - Receive a request from a rport + * fc_rport_recv_req() - Receive a request from a rport * @sp: current sequence in the PLOGI exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -931,7 +931,7 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_rport_recv_plogi_req - Handle incoming Port Login (PLOGI) request + * fc_rport_recv_plogi_req() - Handle incoming Port Login (PLOGI) request * @rport: Fibre Channel remote port that initiated PLOGI * @sp: current sequence in the PLOGI exchange * @fp: PLOGI request frame @@ -1053,7 +1053,7 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport, } /** - * fc_rport_recv_prli_req - Handle incoming Process Login (PRLI) request + * fc_rport_recv_prli_req() - Handle incoming Process Login (PRLI) request * @rport: Fibre Channel remote port that initiated PRLI * @sp: current sequence in the PRLI exchange * @fp: PRLI request frame @@ -1204,7 +1204,7 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport, } /** - * fc_rport_recv_prlo_req - Handle incoming Process Logout (PRLO) request + * fc_rport_recv_prlo_req() - Handle incoming Process Logout (PRLO) request * @rport: Fibre Channel remote port that initiated PRLO * @sp: current sequence in the PRLO exchange * @fp: PRLO request frame @@ -1235,7 +1235,7 @@ static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp, } /** - * fc_rport_recv_logo_req - Handle incoming Logout (LOGO) request + * fc_rport_recv_logo_req() - Handle incoming Logout (LOGO) request * @rport: Fibre Channel remote port that initiated LOGO * @sp: current sequence in the LOGO exchange * @fp: LOGO request frame diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h index 282829cdf352..a2e126b86e3e 100644 --- a/include/scsi/libfc.h +++ b/include/scsi/libfc.h @@ -665,7 +665,7 @@ struct fc_lport { struct delayed_work disc_work; }; -/** +/* * FC_LPORT HELPER FUNCTIONS *****************************/ static inline void *lport_priv(const struct fc_lport *lp) @@ -697,7 +697,7 @@ static inline void fc_lport_state_enter(struct fc_lport *lp, } -/** +/* * LOCAL PORT LAYER *****************************/ int fc_lport_init(struct fc_lport *lp); @@ -747,19 +747,19 @@ int fc_lport_reset(struct fc_lport *); int fc_set_mfs(struct fc_lport *lp, u32 mfs); -/** +/* * REMOTE PORT LAYER *****************************/ int fc_rport_init(struct fc_lport *lp); void fc_rport_terminate_io(struct fc_rport *rp); -/** +/* * DISCOVERY LAYER *****************************/ int fc_disc_init(struct fc_lport *lp); -/** +/* * SCSI LAYER *****************************/ /* @@ -820,7 +820,7 @@ int fc_change_queue_type(struct scsi_device *sdev, int tag_type); */ void fc_fcp_destroy(struct fc_lport *); -/** +/* * ELS/CT interface *****************************/ /* @@ -829,7 +829,7 @@ void fc_fcp_destroy(struct fc_lport *); int fc_elsct_init(struct fc_lport *lp); -/** +/* * EXCHANGE MANAGER LAYER *****************************/ /* -- cgit v1.2.3 From b2ab99c9a300e572105d6db7f6efe0a4d1572167 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:50 -0800 Subject: [SCSI] libfc, fcoe: Cleanup function formatting and minor typos 1) There were a few functions with a strange layout, i.e. all arguments on the second line, when not necessary. Where ever possible I moved the return value to the same line as the function name. However, when the line was too long to have a single argument on the same line I moved the return value to above line. For example: (, ) and (, ) 2) Removed one extra whitespace line 3) Fixed two typos Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fc_transport_fcoe.c | 11 ++++++----- drivers/scsi/fcoe/libfcoe.c | 15 +++++++-------- drivers/scsi/libfc/fc_exch.c | 10 +++++----- drivers/scsi/libfc/fc_rport.c | 4 ++-- 4 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fc_transport_fcoe.c b/drivers/scsi/fcoe/fc_transport_fcoe.c index 0eea4c434c31..847453a70c62 100644 --- a/drivers/scsi/fcoe/fc_transport_fcoe.c +++ b/drivers/scsi/fcoe/fc_transport_fcoe.c @@ -62,8 +62,9 @@ struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev) * * Returns: 0 for success */ -static struct fcoe_transport_internal *fcoe_transport_device_lookup( - struct fcoe_transport *t, struct net_device *netdev) +static struct fcoe_transport_internal * +fcoe_transport_device_lookup(struct fcoe_transport *t, + struct net_device *netdev) { struct fcoe_transport_internal *ti; @@ -184,7 +185,7 @@ static void fcoe_transport_device_remove_all(struct fcoe_transport *t) * Returns: true for match up */ static bool fcoe_transport_match(struct fcoe_transport *t, - struct net_device *netdev) + struct net_device *netdev) { /* match transport by vendor and device id */ struct pci_dev *pci; @@ -217,8 +218,8 @@ static bool fcoe_transport_match(struct fcoe_transport *t, * * TODO: return default sw transport if no other transport is found */ -static struct fcoe_transport *fcoe_transport_lookup( - struct net_device *netdev) +static struct fcoe_transport * +fcoe_transport_lookup(struct net_device *netdev) { struct fcoe_transport *t; diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 5e68652985b2..d006d6576817 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -949,8 +949,8 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer) * * Returns: ptr to the struct module, NULL for failure */ -static struct module *fcoe_netdev_to_module_owner( - const struct net_device *netdev) +static struct module * +fcoe_netdev_to_module_owner(const struct net_device *netdev) { struct device *dev; @@ -1205,8 +1205,8 @@ EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue); * Returns: ptr to Scsi_Host * TODO: to libfc? */ -static inline struct Scsi_Host *libfc_host_alloc( - struct scsi_host_template *sht, int priv_size) +static inline struct Scsi_Host * +libfc_host_alloc(struct scsi_host_template *sht, int priv_size) { return scsi_host_alloc(sht, sizeof(struct fc_lport) + priv_size); } @@ -1285,8 +1285,8 @@ EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac); * * Returns: NULL or the located fcoe_softc */ -static struct fcoe_softc *fcoe_hostlist_lookup_softc( - const struct net_device *dev) +static struct fcoe_softc * +fcoe_hostlist_lookup_softc(const struct net_device *dev) { struct fcoe_softc *fc; @@ -1426,7 +1426,6 @@ static int __init fcoe_init(void) } else { fcoe_percpu[cpu] = NULL; kfree(p); - } } } @@ -1476,7 +1475,7 @@ static void __exit fcoe_exit(void) */ del_timer_sync(&fcoe_timer); - /* releases the assocaited fcoe transport for each lport */ + /* releases the associated fcoe transport for each lport */ list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list) fcoe_transport_release(fc->real_dev); diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 8c4018956d4c..7b933954c107 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -675,8 +675,8 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) * If fc_pf_rjt_reason is FC_RJT_NONE then this function will have a hold * on the ep that should be released by the caller. */ -static enum fc_pf_rjt_reason -fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame *fp) +static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_exch_mgr *mp, + struct fc_frame *fp) { struct fc_frame_header *fh = fc_frame_header_get(fp); struct fc_exch *ep = NULL; @@ -994,9 +994,9 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp) * Send BLS Reject. * This is for rejecting BA_ABTS only. */ -static void -fc_exch_send_ba_rjt(struct fc_frame *rx_fp, enum fc_ba_rjt_reason reason, - enum fc_ba_rjt_explan explan) +static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp, + enum fc_ba_rjt_reason reason, + enum fc_ba_rjt_explan explan) { struct fc_frame *fp; struct fc_frame_header *rx_fh; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 6f07de15c491..dae65133a833 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -179,8 +179,8 @@ EXPORT_SYMBOL(fc_set_rport_loss_tmo); * @flp: FLOGI payload structure * @maxval: upper limit, may be less than what is in the service parameters */ -static unsigned int -fc_plogi_get_maxframe(struct fc_els_flogi *flp, unsigned int maxval) +static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp, + unsigned int maxval) { unsigned int mfs; -- cgit v1.2.3 From fc47ff6b1b27fb736f255ed8cd490356e0cd228f Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:55 -0800 Subject: [SCSI] libfc, fcoe: Remove unnecessary cast by removing inline wrapper Comment from "Andrew Morton " > +{ > + return (struct fcoe_softc *)lport_priv(lp); unneeded/undesirable cast of void*. There are probably zillions of instances of this - there always are. This whole inline function was unnecessary. The FCoE layer knows that it's data structure is stored in the lport private data, it can just access it from lport_priv(). Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe_sw.c | 2 +- drivers/scsi/fcoe/libfcoe.c | 12 ++++++------ include/scsi/libfcoe.h | 8 +------- 3 files changed, 8 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index 007d1fbae808..f667dce1bbba 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -297,7 +297,7 @@ static int fcoe_sw_destroy(struct net_device *netdev) if (!lp) return -ENODEV; - fc = fcoe_softc(lp); + fc = lport_priv(lp); /* Logout of the fabric */ fc_fabric_logoff(lp); diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index d006d6576817..02f044a87159 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -387,7 +387,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) WARN_ON((fr_len(fp) % sizeof(u32)) != 0); - fc = fcoe_softc(lp); + fc = lport_priv(lp); /* * if it is a flogi then we need to learn gw-addr * and my own fcid @@ -768,7 +768,7 @@ static int fcoe_check_wait_queue(struct fc_lport *lp) struct sk_buff *skb; struct fcoe_softc *fc; - fc = fcoe_softc(lp); + fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); /* @@ -805,7 +805,7 @@ static void fcoe_insert_wait_queue_head(struct fc_lport *lp, { struct fcoe_softc *fc; - fc = fcoe_softc(lp); + fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); __skb_queue_head(&fc->fcoe_pending_queue, skb); spin_unlock_bh(&fc->fcoe_pending_queue.lock); @@ -823,7 +823,7 @@ static void fcoe_insert_wait_queue(struct fc_lport *lp, { struct fcoe_softc *fc; - fc = fcoe_softc(lp); + fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); __skb_queue_tail(&fc->fcoe_pending_queue, skb); spin_unlock_bh(&fc->fcoe_pending_queue.lock); @@ -1113,7 +1113,7 @@ MODULE_PARM_DESC(destroy, "Destroy fcoe port"); */ int fcoe_link_ok(struct fc_lport *lp) { - struct fcoe_softc *fc = fcoe_softc(lp); + struct fcoe_softc *fc = lport_priv(lp); struct net_device *dev = fc->real_dev; struct ethtool_cmd ecmd = { ETHTOOL_GSET }; int rc = 0; @@ -1329,7 +1329,7 @@ int fcoe_hostlist_add(const struct fc_lport *lp) fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp)); if (!fc) { - fc = fcoe_softc(lp); + fc = lport_priv(lp); write_lock_bh(&fcoe_hostlist_lock); list_add_tail(&fc->list, &fcoe_hostlist); write_unlock_bh(&fcoe_hostlist_lock); diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index 89fdbb9a6a1b..f43d3833a7a8 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -58,16 +58,10 @@ struct fcoe_softc { u8 address_mode; }; -static inline struct fcoe_softc *fcoe_softc( - const struct fc_lport *lp) -{ - return (struct fcoe_softc *)lport_priv(lp); -} - static inline struct net_device *fcoe_netdev( const struct fc_lport *lp) { - return fcoe_softc(lp)->real_dev; + return ((struct fcoe_softc *)lport_priv(lp))->real_dev; } static inline struct fcoe_hdr *skb_fcoe_header(const struct sk_buff *skb) -- cgit v1.2.3 From a468f328ad83f14556e5961ef1de80b32b428d32 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:56:00 -0800 Subject: [SCSI] fcoe: Use setup_timer() and mod_timer() Use helper functions for watchdog timer setup. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 02f044a87159..7887f2a7c2aa 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -1435,11 +1435,9 @@ static int __init fcoe_init(void) */ fcoe_dev_setup(); - init_timer(&fcoe_timer); - fcoe_timer.data = 0; - fcoe_timer.function = fcoe_watchdog; - fcoe_timer.expires = (jiffies + (10 * HZ)); - add_timer(&fcoe_timer); + setup_timer(&fcoe_timer, fcoe_watchdog, 0); + + mod_timer(&fcoe_timer, jiffies + (10 * HZ)); /* initiatlize the fcoe transport */ fcoe_transport_init(); -- cgit v1.2.3 From 03ec862dff57ca3d1fcb439b99aadc45bc5c2f28 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:56:06 -0800 Subject: [SCSI] fcoe: Correct fcoe_transports initialization vs. registration The registration function shouldn't initialize the mutex or list head. The fcoe SW transport should initialize itself before registering. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fc_transport_fcoe.c | 3 --- drivers/scsi/fcoe/fcoe_sw.c | 5 +++++ 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fc_transport_fcoe.c b/drivers/scsi/fcoe/fc_transport_fcoe.c index 847453a70c62..8862758006c0 100644 --- a/drivers/scsi/fcoe/fc_transport_fcoe.c +++ b/drivers/scsi/fcoe/fc_transport_fcoe.c @@ -258,9 +258,6 @@ int fcoe_transport_register(struct fcoe_transport *t) list_add_tail(&t->list, &fcoe_transports); mutex_unlock(&fcoe_transports_lock); - mutex_init(&t->devlock); - INIT_LIST_HEAD(&t->devlist); - printk(KERN_DEBUG "fcoe_transport_register:%s\n", t->name); return 0; diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index f667dce1bbba..37d359db1648 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -467,10 +467,15 @@ int __init fcoe_sw_init(void) /* attach to scsi transport */ scsi_transport_fcoe_sw = fc_attach_transport(&fcoe_sw_transport_function); + if (!scsi_transport_fcoe_sw) { printk(KERN_ERR "fcoe_sw_init:fc_attach_transport() failed\n"); return -ENODEV; } + + mutex_init(&fcoe_sw_transport.devlock); + INIT_LIST_HEAD(&fcoe_sw_transport.devlist); + /* register sw transport */ fcoe_transport_register(&fcoe_sw_transport); return 0; -- cgit v1.2.3 From 422819cfa3a2605a0b3bdc33aaef0bc2feaeaada Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 27 Feb 2009 10:56:11 -0800 Subject: [SCSI] libfc: do not change the fh_rx_id of a recevied frame We shouldn't be altering inbound frames. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 7b933954c107..505825b6124d 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -625,7 +625,6 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) { struct fc_exch *ep; struct fc_frame_header *fh; - u16 rxid; ep = mp->lp->tt.exch_get(mp->lp, fp); if (ep) { @@ -652,18 +651,6 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) if ((ntoh24(fh->fh_f_ctl) & FC_FC_SEQ_INIT) == 0) ep->esb_stat &= ~ESB_ST_SEQ_INIT; - /* - * Set the responder ID in the frame header. - * The old one should've been 0xffff. - * If it isn't, don't assign one. - * Incoming basic link service frames may specify - * a referenced RX_ID. - */ - if (fh->fh_type != FC_TYPE_BLS) { - rxid = ntohs(fh->fh_rx_id); - WARN_ON(rxid != FC_XID_UNKNOWN); - fh->fh_rx_id = htons(ep->rxid); - } fc_exch_hold(ep); /* hold for caller */ spin_unlock_bh(&ep->ex_lock); /* lock from exch_get */ } -- cgit v1.2.3 From e904158159e9812d06646767b7c81846dc3b05e6 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 27 Feb 2009 10:56:22 -0800 Subject: [SCSI] fcoe: fix kfree(skb) Use kfree_skb instead of kfree for struct sk_buff pointers. Signed-off-by: Roel Kluin Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 7887f2a7c2aa..7265e0937995 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -437,7 +437,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) if (skb_is_nonlinear(skb)) { skb_frag_t *frag; if (fcoe_get_paged_crc_eof(skb, tlen)) { - kfree(skb); + kfree_skb(skb); return -ENOMEM; } frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; -- cgit v1.2.3 From c826a3145736e3baabebccfd0aecfbb6dae059f2 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Fri, 27 Feb 2009 10:56:27 -0800 Subject: [SCSI] fcoe: Out of order tx frames was causing several check condition SCSI status frames followed by these errors in log. [sdp] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE,SUGGEST_OK [sdp] Sense Key : Aborted Command [current] [sdp] Add. Sense: Data phase error This was causing some test apps to exit due to write failure under heavy load. This was due to a race around adding and removing tx frame skb in fcoe_pending_queue, Chris Leech helped me to find that brief unlocking period when pulling skb from fcoe_pending_queue in various contexts (fcoe_watchdog and fcoe_xmit) and then adding skb back into fcoe_pending_queue up on a failed fcoe_start_io could change skb/tx frame order in fcoe_pending_queue. Thanks Chris. This patch allows only single context to pull skb from fcoe_pending_queue at any time to prevent above described ordering issue/race by use of fcoe_pending_queue_active flag. This patch simplified fcoe_watchdog with modified fcoe_check_wait_queue by use of FCOE_LOW_QUEUE_DEPTH instead previously used several conditionals to clear and set lp->qfull. I think FCOE_MAX_QUEUE_DEPTH with FCOE_LOW_QUEUE_DEPTH will work better in re/setting lp->qfull and these could be fine tuned for performance. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe_sw.c | 1 + drivers/scsi/fcoe/libfcoe.c | 45 +++++++++++++++++++++------------------------ include/scsi/libfcoe.h | 1 + 3 files changed, 23 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index 37d359db1648..da210eba1941 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -188,6 +188,7 @@ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) skb_queue_head_init(&fc->fcoe_pending_queue); + fc->fcoe_pending_queue_active = 0; /* setup Source Mac Address */ memcpy(fc->ctl_src_addr, fc->real_dev->dev_addr, diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 7265e0937995..14dd8a0402b6 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -49,6 +49,7 @@ static int debug_fcoe; #define FCOE_MAX_QUEUE_DEPTH 256 +#define FCOE_LOW_QUEUE_DEPTH 32 /* destination address mode */ #define FCOE_GW_ADDR_MODE 0x00 @@ -723,21 +724,12 @@ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) */ void fcoe_watchdog(ulong vp) { - struct fc_lport *lp; struct fcoe_softc *fc; - int qfilled = 0; read_lock(&fcoe_hostlist_lock); list_for_each_entry(fc, &fcoe_hostlist, list) { - lp = fc->lp; - if (lp) { - if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - qfilled = 1; - if (fcoe_check_wait_queue(lp) < FCOE_MAX_QUEUE_DEPTH) { - if (qfilled) - lp->qfull = 0; - } - } + if (fc->lp) + fcoe_check_wait_queue(fc->lp); } read_unlock(&fcoe_hostlist_lock); @@ -753,8 +745,8 @@ void fcoe_watchdog(ulong vp) * * This empties the wait_queue, dequeue the head of the wait_queue queue * and calls fcoe_start_io() for each packet, if all skb have been - * transmitted, return 0 if a error occurs, then restore wait_queue and - * try again later. + * transmitted, return qlen or -1 if a error occurs, then restore + * wait_queue and try again later. * * The wait_queue is used when the skb transmit fails. skb will go * in the wait_queue which will be emptied by the time function OR @@ -764,33 +756,38 @@ void fcoe_watchdog(ulong vp) */ static int fcoe_check_wait_queue(struct fc_lport *lp) { - int rc; struct sk_buff *skb; struct fcoe_softc *fc; + int rc = -1; fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); - /* - * if interface pending queue full then set qfull in lport. - */ - if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - lp->qfull = 1; + if (fc->fcoe_pending_queue_active) + goto out; + fc->fcoe_pending_queue_active = 1; if (fc->fcoe_pending_queue.qlen) { while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) { spin_unlock_bh(&fc->fcoe_pending_queue.lock); rc = fcoe_start_io(skb); - if (rc) { + if (rc) fcoe_insert_wait_queue_head(lp, skb); - return rc; - } spin_lock_bh(&fc->fcoe_pending_queue.lock); + if (rc) + break; } - if (fc->fcoe_pending_queue.qlen < FCOE_MAX_QUEUE_DEPTH) + /* + * if interface pending queue is below FCOE_LOW_QUEUE_DEPTH + * then clear qfull flag. + */ + if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) lp->qfull = 0; } + fc->fcoe_pending_queue_active = 0; + rc = fc->fcoe_pending_queue.qlen; +out: spin_unlock_bh(&fc->fcoe_pending_queue.lock); - return fc->fcoe_pending_queue.qlen; + return rc; } /** diff --git a/include/scsi/libfcoe.h b/include/scsi/libfcoe.h index f43d3833a7a8..941818f29f59 100644 --- a/include/scsi/libfcoe.h +++ b/include/scsi/libfcoe.h @@ -46,6 +46,7 @@ struct fcoe_softc { struct net_device *phys_dev; /* device with ethtool_ops */ struct packet_type fcoe_packet_type; struct sk_buff_head fcoe_pending_queue; + u8 fcoe_pending_queue_active; u8 dest_addr[ETH_ALEN]; u8 ctl_src_addr[ETH_ALEN]; -- cgit v1.2.3 From 55c8bafba549e3e82f6999db8c5a62fc3c255c14 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Fri, 27 Feb 2009 10:56:32 -0800 Subject: [SCSI] fcoe: fix handling of pending queue, prevent out of order frames (v3) In fcoe_check_wait_queue() the queue length could temporarily drop to 0, before the last frame was successfully sent. This resulted in out of order data frames within a single sequence, leading to IO timeout errors. This builds on the approach from Vasu Dev to only fix the queue management in fcoe_check_wait_queue, where my first patch added locking to the transmit path even when the pending queue was not in use. This patch continues to use fcoe_pending_queue.qlen instead of introducing a new length counter, but takes precautions to ensure it never drops to 0 before the final frame in the queue has successfully been passed to the netdev qdisc layer. It also includes some cleanup of fcoe_check_wait_queue and removes the fcoe_insert_wait_queue(_head) wrapper functions. Signed-off-by: Chris Leech Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 81 ++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 14dd8a0402b6..0e0b494fc17c 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -70,8 +70,6 @@ struct fcoe_percpu_s *fcoe_percpu[NR_CPUS]; /* Function Prototyes */ static int fcoe_check_wait_queue(struct fc_lport *); -static void fcoe_insert_wait_queue_head(struct fc_lport *, struct sk_buff *); -static void fcoe_insert_wait_queue(struct fc_lport *, struct sk_buff *); static void fcoe_recv_flogi(struct fcoe_softc *, struct fc_frame *, u8 *); #ifdef CONFIG_HOTPLUG_CPU static int fcoe_cpu_callback(struct notifier_block *, ulong, void *); @@ -501,7 +499,9 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) rc = fcoe_start_io(skb); if (rc) { - fcoe_insert_wait_queue(lp, skb); + spin_lock_bh(&fc->fcoe_pending_queue.lock); + __skb_queue_tail(&fc->fcoe_pending_queue, skb); + spin_unlock_bh(&fc->fcoe_pending_queue.lock); if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) lp->qfull = 1; } @@ -756,33 +756,36 @@ void fcoe_watchdog(ulong vp) */ static int fcoe_check_wait_queue(struct fc_lport *lp) { + struct fcoe_softc *fc = lport_priv(lp); struct sk_buff *skb; - struct fcoe_softc *fc; int rc = -1; - fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); - if (fc->fcoe_pending_queue_active) goto out; fc->fcoe_pending_queue_active = 1; - if (fc->fcoe_pending_queue.qlen) { - while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) { - spin_unlock_bh(&fc->fcoe_pending_queue.lock); - rc = fcoe_start_io(skb); - if (rc) - fcoe_insert_wait_queue_head(lp, skb); - spin_lock_bh(&fc->fcoe_pending_queue.lock); - if (rc) - break; + + while (fc->fcoe_pending_queue.qlen) { + /* keep qlen > 0 until fcoe_start_io succeeds */ + fc->fcoe_pending_queue.qlen++; + skb = __skb_dequeue(&fc->fcoe_pending_queue); + + spin_unlock_bh(&fc->fcoe_pending_queue.lock); + rc = fcoe_start_io(skb); + spin_lock_bh(&fc->fcoe_pending_queue.lock); + + if (rc) { + __skb_queue_head(&fc->fcoe_pending_queue, skb); + /* undo temporary increment above */ + fc->fcoe_pending_queue.qlen--; + break; } - /* - * if interface pending queue is below FCOE_LOW_QUEUE_DEPTH - * then clear qfull flag. - */ - if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) - lp->qfull = 0; + /* undo temporary increment above */ + fc->fcoe_pending_queue.qlen--; } + + if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) + lp->qfull = 0; fc->fcoe_pending_queue_active = 0; rc = fc->fcoe_pending_queue.qlen; out: @@ -790,42 +793,6 @@ out: return rc; } -/** - * fcoe_insert_wait_queue_head() - puts skb to fcoe pending queue head - * @lp: the fc_port for this skb - * @skb: the associated skb to be xmitted - * - * Returns: none - */ -static void fcoe_insert_wait_queue_head(struct fc_lport *lp, - struct sk_buff *skb) -{ - struct fcoe_softc *fc; - - fc = lport_priv(lp); - spin_lock_bh(&fc->fcoe_pending_queue.lock); - __skb_queue_head(&fc->fcoe_pending_queue, skb); - spin_unlock_bh(&fc->fcoe_pending_queue.lock); -} - -/** - * fcoe_insert_wait_queue() - put the skb into fcoe pending queue tail - * @lp: the fc_port for this skb - * @skb: the associated skb to be xmitted - * - * Returns: none - */ -static void fcoe_insert_wait_queue(struct fc_lport *lp, - struct sk_buff *skb) -{ - struct fcoe_softc *fc; - - fc = lport_priv(lp); - spin_lock_bh(&fc->fcoe_pending_queue.lock); - __skb_queue_tail(&fc->fcoe_pending_queue, skb); - spin_unlock_bh(&fc->fcoe_pending_queue.lock); -} - /** * fcoe_dev_setup() - setup link change notification interface */ -- cgit v1.2.3 From 4469c195da43bf8220f53da8b576c0e154c2b662 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:56:38 -0800 Subject: [SCSI] fcoe: Change fcoe receive thread nice value from 19 (lowest priority) to -20 This change makes the fcoe Rx threads have the same nice value as lpfc and qla2xxx Rx threads. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 0e0b494fc17c..5548bf3bb58b 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -531,7 +531,7 @@ int fcoe_percpu_receive_thread(void *arg) struct fcoe_softc *fc; struct fcoe_hdr *hp; - set_user_nice(current, 19); + set_user_nice(current, -20); while (!kthread_should_stop()) { -- cgit v1.2.3 From 6431c5dc5eeaa79863b4af300c081a01e2ccd0bb Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 5 Mar 2009 11:07:00 -0800 Subject: [SCSI] qla2xxx: Correct address range checking for option-rom updates. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index f4c57227ec18..ee9d40152430 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -244,12 +244,6 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, if (ha->optrom_state != QLA_SWAITING) break; - if (start & 0xfff) { - qla_printk(KERN_WARNING, ha, - "Invalid start region 0x%x/0x%x.\n", start, size); - return -EINVAL; - } - ha->optrom_region_start = start; ha->optrom_region_size = start + size > ha->optrom_size ? ha->optrom_size - start : size; @@ -303,8 +297,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, else if (start == (ha->flt_region_boot * 4) || start == (ha->flt_region_fw * 4)) valid = 1; - else if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && - start == (ha->flt_region_vpd_nvram * 4)) + else if (IS_QLA25XX(ha) || IS_QLA81XX(ha)) valid = 1; if (!valid) { qla_printk(KERN_WARNING, ha, -- cgit v1.2.3 From 605aa2bcd5e9dddc4666f12e0c19822809186d6d Mon Sep 17 00:00:00 2001 From: Lalit Chandivade Date: Thu, 5 Mar 2009 11:07:01 -0800 Subject: [SCSI] qla2xxx: Use correct value for max vport in LOOP topology. Use minimum value for max vport during firmware initialization in LOOP topology. Using max vport value from get resource count in LOOP topology causes firmware initialization failure. Signed-off-by: Lalit Chandivade Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 986501759ad4..14325c027336 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1308,8 +1308,12 @@ qla2x00_init_rings(scsi_qla_host_t *vha) DEBUG(printk("scsi(%ld): Issue init firmware.\n", vha->host_no)); - if (ha->flags.npiv_supported) + if (ha->flags.npiv_supported) { + if (ha->operating_mode == LOOP) + ha->max_npiv_vports = MIN_MULTI_ID_FABRIC - 1; mid_init_cb->count = cpu_to_le16(ha->max_npiv_vports); + } + mid_init_cb->options = __constant_cpu_to_le16(BIT_1); -- cgit v1.2.3 From ee546b6e048586381462ce7bb51c7ddc03819619 Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Thu, 5 Mar 2009 11:07:02 -0800 Subject: [SCSI] qla2xxx: Correct vport delete bug. Signed-off-by: Anirban Chakraborty Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 11 +++++++---- drivers/scsi/qla2xxx/qla_mbx.c | 3 ++- drivers/scsi/qla2xxx/qla_mid.c | 10 ++++++---- 3 files changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 14325c027336..e54ab2f10795 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2614,6 +2614,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, port_id_t wrap, nxt_d_id; struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); + struct scsi_qla_host *tvp; rval = QLA_SUCCESS; @@ -2713,7 +2714,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, /* Bypass virtual ports of the same host. */ found = 0; if (ha->num_vhosts) { - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { if (new_fcport->d_id.b24 == vp->d_id.b24) { found = 1; break; @@ -2836,6 +2837,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) uint16_t first_loop_id; struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp; + struct scsi_qla_host *tvp; rval = QLA_SUCCESS; @@ -2860,7 +2862,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) /* Check for loop ID being already in use. */ found = 0; fcport = NULL; - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { list_for_each_entry(fcport, &vp->vp_fcports, list) { if (fcport->loop_id == dev->loop_id && fcport != dev) { @@ -3295,6 +3297,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) uint8_t status = 0; struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp; + struct scsi_qla_host *tvp; struct req_que *req = ha->req_q_map[0]; if (vha->flags.online) { @@ -3310,7 +3313,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) if (atomic_read(&vha->loop_state) != LOOP_DOWN) { atomic_set(&vha->loop_state, LOOP_DOWN); qla2x00_mark_all_devices_lost(vha, 0); - list_for_each_entry(vp, &ha->vp_list, list) + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) qla2x00_mark_all_devices_lost(vp, 0); } else { if (!atomic_read(&vha->loop_down_timer)) @@ -3407,7 +3410,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) DEBUG(printk(KERN_INFO "qla2x00_abort_isp(%ld): succeeded.\n", vha->host_no)); - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { if (vp->vp_idx) qla2x00_vp_abort_isp(vp); } diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 4c7504cb3990..4aab7acf7525 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2685,6 +2685,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, uint16_t stat = le16_to_cpu(rptid_entry->vp_idx); struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *vp; + scsi_qla_host_t *tvp; if (rptid_entry->entry_status != 0) return; @@ -2710,7 +2711,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, if (MSB(stat) == 1) return; - list_for_each_entry(vp, &ha->vp_list, list) + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) if (vp_idx == vp->vp_idx) break; if (!vp) diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 3f23932210c4..785c61279e6e 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -69,9 +69,10 @@ static scsi_qla_host_t * qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name) { scsi_qla_host_t *vha; + struct scsi_qla_host *tvha; /* Locate matching device in database. */ - list_for_each_entry(vha, &ha->vp_list, list) { + list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { if (!memcmp(port_name, vha->port_name, WWN_SIZE)) return vha; } @@ -194,11 +195,11 @@ qla24xx_configure_vp(scsi_qla_host_t *vha) void qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) { - scsi_qla_host_t *vha; + scsi_qla_host_t *vha, *tvha; struct qla_hw_data *ha = rsp->hw; int i = 0; - list_for_each_entry(vha, &ha->vp_list, list) { + list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { if (vha->vp_idx) { switch (mb[0]) { case MBA_LIP_OCCURRED: @@ -300,6 +301,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) int ret; struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *vp; + struct scsi_qla_host *tvp; if (vha->vp_idx) return; @@ -308,7 +310,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) clear_bit(VP_DPC_NEEDED, &vha->dpc_flags); - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { if (vp->vp_idx) ret = qla2x00_do_dpc_vp(vp); } -- cgit v1.2.3 From c6b2fca8205dc33e3bb444835769e4ea4c6bc58d Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 5 Mar 2009 11:07:03 -0800 Subject: [SCSI] qla2xxx: Correct truncation in return-code status checking. QLA_* return codes are 'int' in size. There were still several legacy check-points which assumed a return-code width of 8-bits. This could cause incorrect assumptions of 'good' status if a return of QLA_FUNCTION_TIMEOUT. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 2 +- drivers/scsi/qla2xxx/qla_os.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e54ab2f10795..87f9abc71460 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3435,7 +3435,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) static int qla2x00_restart_isp(scsi_qla_host_t *vha) { - uint8_t status = 0; + int status = 0; uint32_t wait_time; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2f5f72531e23..16c34760b95d 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2568,7 +2568,7 @@ qla2x00_do_work(struct scsi_qla_host *vha) void qla2x00_relogin(struct scsi_qla_host *vha) { fc_port_t *fcport; - uint8_t status; + int status; uint16_t next_loopid = 0; struct qla_hw_data *ha = vha->hw; -- cgit v1.2.3 From ca42f2b5f58702e5751e1423bd2f7987b0760eab Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 5 Mar 2009 11:07:04 -0800 Subject: [SCSI] qla2xxx: Correct overwrite of pre-assigned init-control-block structure size. The value is already pre-assigned prior to the qla2x00_mem_alloc(). Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 16c34760b95d..3ddfa889e949 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2222,10 +2222,6 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, { char name[16]; - ha->init_cb_size = sizeof(init_cb_t); - if (IS_QLA2XXX_MIDTYPE(ha)) - ha->init_cb_size = sizeof(struct mid_init_cb_24xx); - ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size, &ha->init_cb_dma, GFP_KERNEL); if (!ha->init_cb) -- cgit v1.2.3 From 5fa0ae19822d60307059ee64b80ba9e5effdce58 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 5 Mar 2009 11:07:05 -0800 Subject: [SCSI] qla2xxx: Update version number to 8.03.00-k4. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 79f7053da99b..a772eab2f0ea 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.03.00-k3" +#define QLA2XXX_VERSION "8.03.00-k4" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 3 -- cgit v1.2.3 From b70d11da61d751ad968c6f686d83ac1b0ae41466 Mon Sep 17 00:00:00 2001 From: Kristian Høgsberg Date: Tue, 3 Mar 2009 14:45:57 -0500 Subject: drm: Return EINVAL on duplicate objects in execbuffer object list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If userspace passes an object list with the same object appearing more than once, we end up hitting the BUG_ON() in i915_gem_object_set_to_gpu_domain() as it gets called a second time for the same object. Signed-off-by: Kristian Høgsberg Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 6 ++++++ drivers/gpu/drm/i915/i915_gem.c | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 17fa40858d26..9186d43be011 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -457,6 +457,12 @@ struct drm_i915_gem_object { /** for phy allocated objects */ struct drm_i915_gem_phys_object *phys_obj; + + /** + * Used for checking the object doesn't appear more than once + * in an execbuffer object list. + */ + int in_execbuffer; }; /** diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 85685bfd12da..7bdcc752f139 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2469,6 +2469,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_i915_gem_exec_object *exec_list = NULL; struct drm_gem_object **object_list = NULL; struct drm_gem_object *batch_obj; + struct drm_i915_gem_object *obj_priv; int ret, i, pinned = 0; uint64_t exec_offset; uint32_t seqno, flush_domains; @@ -2533,6 +2534,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ret = -EBADF; goto err; } + + obj_priv = object_list[i]->driver_private; + if (obj_priv->in_execbuffer) { + DRM_ERROR("Object %p appears more than once in object list\n", + object_list[i]); + ret = -EBADF; + goto err; + } + obj_priv->in_execbuffer = true; } /* Pin and relocate */ @@ -2674,8 +2684,13 @@ err: for (i = 0; i < pinned; i++) i915_gem_object_unpin(object_list[i]); - for (i = 0; i < args->buffer_count; i++) + for (i = 0; i < args->buffer_count; i++) { + if (object_list[i]) { + obj_priv = object_list[i]->driver_private; + obj_priv->in_execbuffer = false; + } drm_gem_object_unreference(object_list[i]); + } mutex_unlock(&dev->struct_mutex); -- cgit v1.2.3 From 0fce81e3ccd093f4826de40fbd27fac9632f6170 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Sat, 28 Feb 2009 15:01:16 -0500 Subject: i915: add newline to i915_gem_object_pin failure msg Prevents formatting nasty as below: [drm:i915_gem_object_pin] *ERROR* Failure to bind: -12<3>[drm:i915_gem_evict_something] *ERROR* inactive empty 1 request empty 1 flushing empty 1 Signed-off-by: Kyle McMartin Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 7bdcc752f139..c94069b28a47 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2727,7 +2727,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) ret = i915_gem_object_bind_to_gtt(obj, alignment); if (ret != 0) { if (ret != -EBUSY && ret != -ERESTARTSYS) - DRM_ERROR("Failure to bind: %d", ret); + DRM_ERROR("Failure to bind: %d\n", ret); return ret; } /* -- cgit v1.2.3 From 66824bd7b5dc22da367595359bfcd1149c4ce92a Mon Sep 17 00:00:00 2001 From: Pierre Willenbrock Date: Wed, 25 Feb 2009 17:49:51 +0100 Subject: drm/i915: Don't restore palettes through VGA registers. The VGA registers just hit the pipe registers that we already set through MMIO. This fixes strange colors on resume. Signed-off-by: Pierre Willenbrock Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_suspend.c | 11 ----------- 2 files changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9186d43be011..d6cc9861e0a1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -279,7 +279,6 @@ typedef struct drm_i915_private { u8 saveAR_INDEX; u8 saveAR[21]; u8 saveDACMASK; - u8 saveDACDATA[256*3]; /* 256 3-byte colors */ u8 saveCR[37]; struct { diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 5d84027ee8f3..d669cc2b42c0 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -119,11 +119,6 @@ static void i915_save_vga(struct drm_device *dev) /* VGA color palette registers */ dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK); - /* DACCRX automatically increments during read */ - I915_WRITE8(VGA_DACRX, 0); - /* Read 3 bytes of color data from each index */ - for (i = 0; i < 256 * 3; i++) - dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA); /* MSR bits */ dev_priv->saveMSR = I915_READ8(VGA_MSR_READ); @@ -225,12 +220,6 @@ static void i915_restore_vga(struct drm_device *dev) /* VGA color palette registers */ I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK); - /* DACCRX automatically increments during read */ - I915_WRITE8(VGA_DACWX, 0); - /* Read 3 bytes of color data from each index */ - for (i = 0; i < 256 * 3; i++) - I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]); - } int i915_save_state(struct drm_device *dev) -- cgit v1.2.3 From 040aefa263aa9cd7bd5df50586c35e1e15e77f84 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 10 Mar 2009 12:31:12 -0700 Subject: drm/i915: Fix bad \n in MTRR failure notice. Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 6dab63bdc4c1..6d21b9e48b89 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1105,7 +1105,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) 1024 * 1024, MTRR_TYPE_WRCOMB, 1); if (dev_priv->mm.gtt_mtrr < 0) { - DRM_INFO("MTRR allocation failed\n. Graphics " + DRM_INFO("MTRR allocation failed. Graphics " "performance may suffer.\n"); } -- cgit v1.2.3 From 48e7a3c95c9f98c2cb6f894820e3cc2d0448e92f Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 10 Mar 2009 22:43:56 +0100 Subject: HID: fix incorrect free in hiddev If hiddev_open() fails, it wrongly frees the shared hiddev structure kept in hiddev_table instead of the hiddev_list structure allocated for the opened file descriptor. Existing references to this structure will then accessed free memory. This was introduced by 079034073 "HID: hiddev cleanup -- handle all error conditions properly". Signed-off-by: Johannes Weiner Cc: Oliver Neukum Cc: Jiri Kosina Signed-off-by: Andrew Morton Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 4940e4d70c2d..00ea1ed282a9 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -306,7 +306,7 @@ static int hiddev_open(struct inode *inode, struct file *file) return 0; bail: file->private_data = NULL; - kfree(list->hiddev); + kfree(list); return res; } -- cgit v1.2.3 From 96fe2ab830d7dffee1b3d8abf27ced4d7d5765e7 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 10 Mar 2009 22:44:01 +0100 Subject: HID: fix waitqueue usage in hiddev DECLARE_WAITQUEUE doesn't initialize the wait descriptor's task_list to 'empty' but to zero. prepare_to_wait() will not enqueue the descriptor to the waitqueue and finish_wait() will do list_del_init() on a list head that contains NULL pointers, which oopses. This was introduced by 079034073 "HID: hiddev cleanup -- handle all error conditions properly". The prior code used an unconditional add_to_waitqueue() which didn't care about the wait descriptor's list head and enqueued the thing unconditionally. The new code uses prepare_to_wait() which DOES check the prior list state, so use DEFINE_WAIT instead. Signed-off-by: Johannes Weiner Cc: Oliver Neukum Cc: Jiri Kosina Signed-off-by: Andrew Morton Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 00ea1ed282a9..1f5b5d4c3c34 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -323,7 +323,7 @@ static ssize_t hiddev_write(struct file * file, const char __user * buffer, size */ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) { - DECLARE_WAITQUEUE(wait, current); + DEFINE_WAIT(wait); struct hiddev_list *list = file->private_data; int event_size; int retval; -- cgit v1.2.3 From 187cfc439f7b1a7c91ff72d561b2a7c9c0b83431 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 9 Mar 2009 14:36:15 +0000 Subject: hvc_console: Remove tty->low_latency on pseries backends The hvcs and hvsi backends both set tty->low_latency to one, along with more or less scary comments regarding bugs or races that would happen if not doing so. However, they also both call tty_flip_buffer_push() in conexts where it's illegal to do so since some recent tty changes (or at least it may have been illegal always but it nows blows) when low_latency is set (ie, hard interrupt or with spinlock held and irqs disabled). This removes the setting for now to get them back to working condition, we'll have to address the races described in the comments separately if they are still an issue (some of this might have been fixed already). Signed-off-by: Benjamin Herrenschmidt --- drivers/char/hvcs.c | 9 --------- drivers/char/hvsi.c | 1 - 2 files changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 6e6eb445d374..c76bccf5354d 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c @@ -1139,15 +1139,6 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) hvcsd->tty = tty; tty->driver_data = hvcsd; - /* - * Set this driver to low latency so that we actually have a chance at - * catching a throttled TTY after we flip_buffer_push. Otherwise the - * flush_to_async may not execute until after the kernel_thread has - * yielded and resumed the next flip_buffer_push resulting in data - * loss. - */ - tty->low_latency = 1; - memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN); /* diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 406f8742a260..2989056a9e39 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -810,7 +810,6 @@ static int hvsi_open(struct tty_struct *tty, struct file *filp) hp = &hvsi_ports[line]; tty->driver_data = hp; - tty->low_latency = 1; /* avoid throttle/tty_flip_buffer_push race */ mb(); if (hp->state == HVSI_FSP_DIED) -- cgit v1.2.3 From d801cec70d69d2d4121e133edd5c3237fe0e0078 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 11 Mar 2009 10:45:17 +1100 Subject: radeonfb/aty128fb: Disable broken early resume hook for PowerBooks radeonfb and aty128fb have a special hook called by the PowerMac platform code very very early on resume from sleep to bring the screen back. This is useful for debugging wakup problems, but unfortunately, this also became a source of problems of its own. The hook is called extremely early, with interrupts still off, and the code path involved with that code nowadays rely on things like taking mutexes, GFP_KERNEL allocations, etc... In addition, the driver now relies on the PCI core to restore the standard config space before calling resume which doesn't happen with this early code path. I'm keeping the code in but commented out along with a fixup call to pci_restore_state(). The reason is that I still want to make it easy to re-enable temporarily to track wake up problems, and it's possible that I can revive it at some stage if we make sleeping things save to call in early resume using a system state. In the meantime, this should fix several reported regressions. Signed-off-by: Benjamin Herrenschmidt --- drivers/video/aty/aty128fb.c | 10 +++++++++- drivers/video/aty/radeon_pm.c | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 2181ce4d7ebd..35e8eb02b9e9 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -1853,13 +1853,14 @@ static void aty128_bl_exit(struct backlight_device *bd) * Initialisation */ -#ifdef CONFIG_PPC_PMAC +#ifdef CONFIG_PPC_PMAC__disabled static void aty128_early_resume(void *data) { struct aty128fb_par *par = data; if (try_acquire_console_sem()) return; + pci_restore_state(par->pdev); aty128_do_resume(par->pdev); release_console_sem(); } @@ -1907,7 +1908,14 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i /* Indicate sleep capability */ if (par->chip_gen == rage_M3) { pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1); +#if 0 /* Disable the early video resume hack for now as it's causing problems, among + * others we now rely on the PCI core restoring the config space for us, which + * isn't the case with that hack, and that code path causes various things to + * be called with interrupts off while they shouldn't. I'm leaving the code in + * as it can be useful for debugging purposes + */ pmac_set_early_video_resume(aty128_early_resume, par); +#endif } /* Find default mode */ diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index ca5f0dc28546..81603f85e17e 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -2762,12 +2762,13 @@ int radeonfb_pci_resume(struct pci_dev *pdev) return rc; } -#ifdef CONFIG_PPC_OF +#ifdef CONFIG_PPC_OF__disabled static void radeonfb_early_resume(void *data) { struct radeonfb_info *rinfo = data; rinfo->no_schedule = 1; + pci_restore_state(rinfo->pdev); radeonfb_pci_resume(rinfo->pdev); rinfo->no_schedule = 0; } @@ -2834,7 +2835,14 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlis */ if (rinfo->pm_mode != radeon_pm_none) { pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, rinfo->of_node, 0, 1); +#if 0 /* Disable the early video resume hack for now as it's causing problems, among + * others we now rely on the PCI core restoring the config space for us, which + * isn't the case with that hack, and that code path causes various things to + * be called with interrupts off while they shouldn't. I'm leaving the code in + * as it can be useful for debugging purposes + */ pmac_set_early_video_resume(radeonfb_early_resume, rinfo); +#endif } #if 0 -- cgit v1.2.3 From 9b2412f9ad0a3913baa40c270d6e1fa3c6d50067 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Feb 2009 14:26:44 +0000 Subject: drm/i915: First recheck for an empty fence register. If we wait upon a request and successfully unbind a buffer occupying a fence register, then that slot will be freed and cause a NULL derefrence upon rescanning. Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c94069b28a47..6497c1ad02d3 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1580,6 +1580,7 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) } /* First try to find a free reg */ +try_again: for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { reg = &dev_priv->fence_regs[i]; if (!reg->obj) @@ -1591,7 +1592,6 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) struct drm_i915_gem_object *old_obj_priv = NULL; loff_t offset; -try_again: /* Could try to use LRU here instead... */ for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { -- cgit v1.2.3 From 22c344e9a03beeb7071a588a973012749f84a830 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Feb 2009 14:26:45 +0000 Subject: drm/i915: Check fence status on every pin. As we may steal the fence register of an unpinned buffer for another, every time we repin the buffer we need to recheck whether it needs to be allocated a fence. Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6497c1ad02d3..12c7d78d9240 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2730,14 +2730,21 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) DRM_ERROR("Failure to bind: %d\n", ret); return ret; } - /* - * Pre-965 chips need a fence register set up in order to - * properly handle tiled surfaces. - */ - if (!IS_I965G(dev) && - obj_priv->fence_reg == I915_FENCE_REG_NONE && - obj_priv->tiling_mode != I915_TILING_NONE) - i915_gem_object_get_fence_reg(obj, true); + } + /* + * Pre-965 chips need a fence register set up in order to + * properly handle tiled surfaces. + */ + if (!IS_I965G(dev) && + obj_priv->fence_reg == I915_FENCE_REG_NONE && + obj_priv->tiling_mode != I915_TILING_NONE) { + ret = i915_gem_object_get_fence_reg(obj, true); + if (ret != 0) { + if (ret != -EBUSY && ret != -ERESTARTSYS) + DRM_ERROR("Failure to install fence: %d\n", + ret); + return ret; + } } obj_priv->pin_count++; -- cgit v1.2.3 From fc7170ba281c041852eeda52d4faf5db720c99ce Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Feb 2009 14:26:46 +0000 Subject: drm/i915: Check to see if we've pinned all available fences We need to check and report if there are no available fences - or else we spin endlessly waiting for a buffer to magically unpin itself. Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 12c7d78d9240..2b5c7ad9e64a 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1557,7 +1557,8 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj_priv = obj->driver_private; struct drm_i915_fence_reg *reg = NULL; - int i, ret; + struct drm_i915_gem_object *old_obj_priv = NULL; + int i, ret, avail; switch (obj_priv->tiling_mode) { case I915_TILING_NONE: @@ -1581,17 +1582,24 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) /* First try to find a free reg */ try_again: + avail = 0; for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { reg = &dev_priv->fence_regs[i]; if (!reg->obj) break; + + old_obj_priv = reg->obj->driver_private; + if (!old_obj_priv->pin_count) + avail++; } /* None available, try to steal one or wait for a user to finish */ if (i == dev_priv->num_fence_regs) { - struct drm_i915_gem_object *old_obj_priv = NULL; loff_t offset; + if (avail == 0) + return -ENOMEM; + /* Could try to use LRU here instead... */ for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { -- cgit v1.2.3 From d7619c4b9c95cc9a2e7f0f4f7ae21165ab5cb1e7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Feb 2009 14:26:47 +0000 Subject: drm/i915: Protect active fences on i915 The i915 also uses the fence registers for GPU access to tiled buffers so we cannot reallocate one whilst it is on the active list. By performing a LRU scan of the fenced buffers we also avoid waiting the possibility of waiting on a pinned, or otherwise unusable, buffer. Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2b5c7ad9e64a..b0ff5c44e61e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1595,18 +1595,32 @@ try_again: /* None available, try to steal one or wait for a user to finish */ if (i == dev_priv->num_fence_regs) { + uint32_t seqno = dev_priv->mm.next_gem_seqno; loff_t offset; if (avail == 0) return -ENOMEM; - /* Could try to use LRU here instead... */ for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { + uint32_t this_seqno; + reg = &dev_priv->fence_regs[i]; old_obj_priv = reg->obj->driver_private; - if (!old_obj_priv->pin_count) + + if (old_obj_priv->pin_count) + continue; + + /* i915 uses fences for GPU access to tiled buffers */ + if (IS_I965G(dev) || !old_obj_priv->active) break; + + /* find the seqno of the first available fence */ + this_seqno = old_obj_priv->last_rendering_seqno; + if (this_seqno != 0 && + reg->obj->write_domain == 0 && + i915_seqno_passed(seqno, this_seqno)) + seqno = this_seqno; } /* @@ -1614,15 +1628,25 @@ try_again: * objects to finish before trying again. */ if (i == dev_priv->num_fence_regs) { - ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0); - if (ret) { - WARN(ret != -ERESTARTSYS, - "switch to GTT domain failed: %d\n", ret); - return ret; + if (seqno == dev_priv->mm.next_gem_seqno) { + i915_gem_flush(dev, + I915_GEM_GPU_DOMAINS, + I915_GEM_GPU_DOMAINS); + seqno = i915_add_request(dev, + I915_GEM_GPU_DOMAINS); + if (seqno == 0) + return -ENOMEM; } + + ret = i915_wait_request(dev, seqno); + if (ret) + return ret; goto try_again; } + BUG_ON(old_obj_priv->active || + (reg->obj->write_domain & I915_GEM_GPU_DOMAINS)); + /* * Zap this virtual mapping so we can set up a fence again * for this object next time we need it. -- cgit v1.2.3 From dc529a4fe1ae4667c819437a94185e8581e1e680 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 10 Mar 2009 22:34:49 -0700 Subject: drm/i915: fix 945 fence register writes for fence 8 and above. The last 8 fence registers sit at a different offset, so when we went to set fence number 8 in the lower offset, we instead set PGETBL_CTL, and the GPU got all sorts of angry at us. fd.o bug #20567. Easily reproducible by running glxgears and killing it about 6 times. Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 21 +++++++++++++++++---- drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b0ff5c44e61e..37427e4016cb 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1476,7 +1476,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) struct drm_i915_gem_object *obj_priv = obj->driver_private; int regnum = obj_priv->fence_reg; int tile_width; - uint32_t val; + uint32_t fence_reg, val; uint32_t pitch_val; if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || @@ -1503,7 +1503,11 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) val |= pitch_val << I830_FENCE_PITCH_SHIFT; val |= I830_FENCE_REG_VALID; - I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); + if (regnum < 8) + fence_reg = FENCE_REG_830_0 + (regnum * 4); + else + fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4); + I915_WRITE(fence_reg, val); } static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) @@ -1687,8 +1691,17 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj) if (IS_I965G(dev)) I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); - else - I915_WRITE(FENCE_REG_830_0 + (obj_priv->fence_reg * 4), 0); + else { + uint32_t fence_reg; + + if (obj_priv->fence_reg < 8) + fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4; + else + fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - + 8) * 4; + + I915_WRITE(fence_reg, 0); + } dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL; obj_priv->fence_reg = I915_FENCE_REG_NONE; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9d6539a868b3..90600d899413 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -184,6 +184,7 @@ * Fence registers */ #define FENCE_REG_830_0 0x2000 +#define FENCE_REG_945_8 0x3000 #define I830_FENCE_START_MASK 0x07f80000 #define I830_FENCE_TILING_Y_SHIFT 12 #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) -- cgit v1.2.3 From 4796417417a62e2ae83d92cb92e1ecf9ec67b5f5 Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Wed, 11 Mar 2009 23:26:02 -0700 Subject: dnet: Dave DNET ethernet controller driver (updated) Driver for Dave DNET ethernet controller found on Dave/DENX QongEVB-LITE FPGA. Heavily based on Dave sources, I've just adopted it to current kernel version and done some code cleanup. Signed-off-by: Ilya Yanok Signed-off-by: David S. Miller --- drivers/net/Kconfig | 11 + drivers/net/Makefile | 1 + drivers/net/dnet.c | 994 +++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/dnet.h | 225 ++++++++++++ 4 files changed, 1231 insertions(+) create mode 100644 drivers/net/dnet.c create mode 100644 drivers/net/dnet.h (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index a2f185fd7072..5c28b06dac6e 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1040,6 +1040,17 @@ config NI65 To compile this driver as a module, choose M here. The module will be called ni65. +config DNET + tristate "Dave ethernet support (DNET)" + depends on NET_ETHERNET + select PHYLIB + help + The Dave ethernet interface (DNET) is found on Qong Board FPGA. + Say Y to include support for the DNET chip. + + To compile this driver as a module, choose M here: the module + will be called dnet. + source "drivers/net/tulip/Kconfig" config AT1700 diff --git a/drivers/net/Makefile b/drivers/net/Makefile index aca8492db654..6d9bba58b9a4 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -231,6 +231,7 @@ obj-$(CONFIG_ENC28J60) += enc28j60.o obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o +obj-$(CONFIG_DNET) += dnet.o obj-$(CONFIG_MACB) += macb.o obj-$(CONFIG_ARM) += arm/ diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c new file mode 100644 index 000000000000..92c3bd3a4721 --- /dev/null +++ b/drivers/net/dnet.c @@ -0,0 +1,994 @@ +/* + * Dave DNET Ethernet Controller driver + * + * Copyright (C) 2008 Dave S.r.l. + * Copyright (C) 2009 Ilya Yanok, Emcraft Systems Ltd, + * + * 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dnet.h" + +#undef DEBUG + +/* function for reading internal MAC register */ +u16 dnet_readw_mac(struct dnet *bp, u16 reg) +{ + u16 data_read; + + /* issue a read */ + dnet_writel(bp, reg, MACREG_ADDR); + + /* since a read/write op to the MAC is very slow, + * we must wait before reading the data */ + ndelay(500); + + /* read data read from the MAC register */ + data_read = dnet_readl(bp, MACREG_DATA); + + /* all done */ + return data_read; +} + +/* function for writing internal MAC register */ +void dnet_writew_mac(struct dnet *bp, u16 reg, u16 val) +{ + /* load data to write */ + dnet_writel(bp, val, MACREG_DATA); + + /* issue a write */ + dnet_writel(bp, reg | DNET_INTERNAL_WRITE, MACREG_ADDR); + + /* since a read/write op to the MAC is very slow, + * we must wait before exiting */ + ndelay(500); +} + +static void __dnet_set_hwaddr(struct dnet *bp) +{ + u16 tmp; + + tmp = cpu_to_be16(*((u16 *) bp->dev->dev_addr)); + dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG, tmp); + tmp = cpu_to_be16(*((u16 *) (bp->dev->dev_addr + 2))); + dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG, tmp); + tmp = cpu_to_be16(*((u16 *) (bp->dev->dev_addr + 4))); + dnet_writew_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG, tmp); +} + +static void __devinit dnet_get_hwaddr(struct dnet *bp) +{ + u16 tmp; + u8 addr[6]; + + /* + * from MAC docs: + * "Note that the MAC address is stored in the registers in Hexadecimal + * form. For example, to set the MAC Address to: AC-DE-48-00-00-80 + * would require writing 0xAC (octet 0) to address 0x0B (high byte of + * Mac_addr[15:0]), 0xDE (octet 1) to address 0x0A (Low byte of + * Mac_addr[15:0]), 0x48 (octet 2) to address 0x0D (high byte of + * Mac_addr[15:0]), 0x00 (octet 3) to address 0x0C (Low byte of + * Mac_addr[15:0]), 0x00 (octet 4) to address 0x0F (high byte of + * Mac_addr[15:0]), and 0x80 (octet 5) to address * 0x0E (Low byte of + * Mac_addr[15:0]). + */ + tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_0_REG); + *((u16 *) addr) = be16_to_cpu(tmp); + tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_1_REG); + *((u16 *) (addr + 2)) = be16_to_cpu(tmp); + tmp = dnet_readw_mac(bp, DNET_INTERNAL_MAC_ADDR_2_REG); + *((u16 *) (addr + 4)) = be16_to_cpu(tmp); + + if (is_valid_ether_addr(addr)) + memcpy(bp->dev->dev_addr, addr, sizeof(addr)); +} + +static int dnet_mdio_read(struct mii_bus *bus, int mii_id, int regnum) +{ + struct dnet *bp = bus->priv; + u16 value; + + while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) + & DNET_INTERNAL_GMII_MNG_CMD_FIN)) + cpu_relax(); + + /* only 5 bits allowed for phy-addr and reg_offset */ + mii_id &= 0x1f; + regnum &= 0x1f; + + /* prepare reg_value for a read */ + value = (mii_id << 8); + value |= regnum; + + /* write control word */ + dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG, value); + + /* wait for end of transfer */ + while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) + & DNET_INTERNAL_GMII_MNG_CMD_FIN)) + cpu_relax(); + + value = dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_DAT_REG); + + pr_debug("mdio_read %02x:%02x <- %04x\n", mii_id, regnum, value); + + return value; +} + +static int dnet_mdio_write(struct mii_bus *bus, int mii_id, int regnum, + u16 value) +{ + struct dnet *bp = bus->priv; + u16 tmp; + + pr_debug("mdio_write %02x:%02x <- %04x\n", mii_id, regnum, value); + + while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) + & DNET_INTERNAL_GMII_MNG_CMD_FIN)) + cpu_relax(); + + /* prepare for a write operation */ + tmp = (1 << 13); + + /* only 5 bits allowed for phy-addr and reg_offset */ + mii_id &= 0x1f; + regnum &= 0x1f; + + /* only 16 bits on data */ + value &= 0xffff; + + /* prepare reg_value for a write */ + tmp |= (mii_id << 8); + tmp |= regnum; + + /* write data to write first */ + dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_DAT_REG, value); + + /* write control word */ + dnet_writew_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG, tmp); + + while (!(dnet_readw_mac(bp, DNET_INTERNAL_GMII_MNG_CTL_REG) + & DNET_INTERNAL_GMII_MNG_CMD_FIN)) + cpu_relax(); + + return 0; +} + +static int dnet_mdio_reset(struct mii_bus *bus) +{ + return 0; +} + +static void dnet_handle_link_change(struct net_device *dev) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; + unsigned long flags; + u32 mode_reg, ctl_reg; + + int status_change = 0; + + spin_lock_irqsave(&bp->lock, flags); + + mode_reg = dnet_readw_mac(bp, DNET_INTERNAL_MODE_REG); + ctl_reg = dnet_readw_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG); + + if (phydev->link) { + if (bp->duplex != phydev->duplex) { + if (phydev->duplex) + ctl_reg &= + ~(DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP); + else + ctl_reg |= + DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP; + + bp->duplex = phydev->duplex; + status_change = 1; + } + + if (bp->speed != phydev->speed) { + status_change = 1; + switch (phydev->speed) { + case 1000: + mode_reg |= DNET_INTERNAL_MODE_GBITEN; + break; + case 100: + case 10: + mode_reg &= ~DNET_INTERNAL_MODE_GBITEN; + break; + default: + printk(KERN_WARNING + "%s: Ack! Speed (%d) is not " + "10/100/1000!\n", dev->name, + phydev->speed); + break; + } + bp->speed = phydev->speed; + } + } + + if (phydev->link != bp->link) { + if (phydev->link) { + mode_reg |= + (DNET_INTERNAL_MODE_RXEN | DNET_INTERNAL_MODE_TXEN); + } else { + mode_reg &= + ~(DNET_INTERNAL_MODE_RXEN | + DNET_INTERNAL_MODE_TXEN); + bp->speed = 0; + bp->duplex = -1; + } + bp->link = phydev->link; + + status_change = 1; + } + + if (status_change) { + dnet_writew_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG, ctl_reg); + dnet_writew_mac(bp, DNET_INTERNAL_MODE_REG, mode_reg); + } + + spin_unlock_irqrestore(&bp->lock, flags); + + if (status_change) { + if (phydev->link) + printk(KERN_INFO "%s: link up (%d/%s)\n", + dev->name, phydev->speed, + DUPLEX_FULL == phydev->duplex ? "Full" : "Half"); + else + printk(KERN_INFO "%s: link down\n", dev->name); + } +} + +static int dnet_mii_probe(struct net_device *dev) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = NULL; + int phy_addr; + + /* find the first phy */ + for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) { + if (bp->mii_bus->phy_map[phy_addr]) { + phydev = bp->mii_bus->phy_map[phy_addr]; + break; + } + } + + if (!phydev) { + printk(KERN_ERR "%s: no PHY found\n", dev->name); + return -ENODEV; + } + + /* TODO : add pin_irq */ + + /* attach the mac to the phy */ + if (bp->capabilities & DNET_HAS_RMII) { + phydev = phy_connect(dev, phydev->dev.bus_id, + &dnet_handle_link_change, 0, + PHY_INTERFACE_MODE_RMII); + } else { + phydev = phy_connect(dev, phydev->dev.bus_id, + &dnet_handle_link_change, 0, + PHY_INTERFACE_MODE_MII); + } + + if (IS_ERR(phydev)) { + printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); + return PTR_ERR(phydev); + } + + /* mask with MAC supported features */ + if (bp->capabilities & DNET_HAS_GIGABIT) + phydev->supported &= PHY_GBIT_FEATURES; + else + phydev->supported &= PHY_BASIC_FEATURES; + + phydev->supported |= SUPPORTED_Asym_Pause | SUPPORTED_Pause; + + phydev->advertising = phydev->supported; + + bp->link = 0; + bp->speed = 0; + bp->duplex = -1; + bp->phy_dev = phydev; + + return 0; +} + +static int dnet_mii_init(struct dnet *bp) +{ + int err, i; + + bp->mii_bus = mdiobus_alloc(); + if (bp->mii_bus == NULL) + return -ENOMEM; + + bp->mii_bus->name = "dnet_mii_bus"; + bp->mii_bus->read = &dnet_mdio_read; + bp->mii_bus->write = &dnet_mdio_write; + bp->mii_bus->reset = &dnet_mdio_reset; + + snprintf(bp->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0); + + bp->mii_bus->priv = bp; + + bp->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL); + if (!bp->mii_bus->irq) { + err = -ENOMEM; + goto err_out; + } + + for (i = 0; i < PHY_MAX_ADDR; i++) + bp->mii_bus->irq[i] = PHY_POLL; + + platform_set_drvdata(bp->dev, bp->mii_bus); + + if (mdiobus_register(bp->mii_bus)) { + err = -ENXIO; + goto err_out_free_mdio_irq; + } + + if (dnet_mii_probe(bp->dev) != 0) { + err = -ENXIO; + goto err_out_unregister_bus; + } + + return 0; + +err_out_unregister_bus: + mdiobus_unregister(bp->mii_bus); +err_out_free_mdio_irq: + kfree(bp->mii_bus->irq); +err_out: + mdiobus_free(bp->mii_bus); + return err; +} + +/* For Neptune board: LINK1000 as Link LED and TX as activity LED */ +int dnet_phy_marvell_fixup(struct phy_device *phydev) +{ + return phy_write(phydev, 0x18, 0x4148); +} + +static void dnet_update_stats(struct dnet *bp) +{ + u32 __iomem *reg = bp->regs + DNET_RX_PKT_IGNR_CNT; + u32 *p = &bp->hw_stats.rx_pkt_ignr; + u32 *end = &bp->hw_stats.rx_byte + 1; + + WARN_ON((unsigned long)(end - p - 1) != + (DNET_RX_BYTE_CNT - DNET_RX_PKT_IGNR_CNT) / 4); + + for (; p < end; p++, reg++) + *p += readl(reg); + + reg = bp->regs + DNET_TX_UNICAST_CNT; + p = &bp->hw_stats.tx_unicast; + end = &bp->hw_stats.tx_byte + 1; + + WARN_ON((unsigned long)(end - p - 1) != + (DNET_TX_BYTE_CNT - DNET_TX_UNICAST_CNT) / 4); + + for (; p < end; p++, reg++) + *p += readl(reg); +} + +static int dnet_poll(struct napi_struct *napi, int budget) +{ + struct dnet *bp = container_of(napi, struct dnet, napi); + struct net_device *dev = bp->dev; + int npackets = 0; + unsigned int pkt_len; + struct sk_buff *skb; + unsigned int *data_ptr; + u32 int_enable; + u32 cmd_word; + int i; + + while (npackets < budget) { + /* + * break out of while loop if there are no more + * packets waiting + */ + if (!(dnet_readl(bp, RX_FIFO_WCNT) >> 16)) { + netif_rx_complete(napi); + int_enable = dnet_readl(bp, INTR_ENB); + int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF; + dnet_writel(bp, int_enable, INTR_ENB); + return 0; + } + + cmd_word = dnet_readl(bp, RX_LEN_FIFO); + pkt_len = cmd_word & 0xFFFF; + + if (cmd_word & 0xDF180000) + printk(KERN_ERR "%s packet receive error %x\n", + __func__, cmd_word); + + skb = dev_alloc_skb(pkt_len + 5); + if (skb != NULL) { + /* Align IP on 16 byte boundaries */ + skb_reserve(skb, 2); + /* + * 'skb_put()' points to the start of sk_buff + * data area. + */ + data_ptr = (unsigned int *)skb_put(skb, pkt_len); + for (i = 0; i < (pkt_len + 3) >> 2; i++) + *data_ptr++ = dnet_readl(bp, RX_DATA_FIFO); + skb->protocol = eth_type_trans(skb, dev); + netif_receive_skb(skb); + npackets++; + } else + printk(KERN_NOTICE + "%s: No memory to allocate a sk_buff of " + "size %u.\n", dev->name, pkt_len); + } + + budget -= npackets; + + if (npackets < budget) { + /* We processed all packets available. Tell NAPI it can + * stop polling then re-enable rx interrupts */ + netif_rx_complete(napi); + int_enable = dnet_readl(bp, INTR_ENB); + int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF; + dnet_writel(bp, int_enable, INTR_ENB); + return 0; + } + + /* There are still packets waiting */ + return 1; +} + +static irqreturn_t dnet_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + struct dnet *bp = netdev_priv(dev); + u32 int_src, int_enable, int_current; + unsigned long flags; + unsigned int handled = 0; + + spin_lock_irqsave(&bp->lock, flags); + + /* read and clear the DNET irq (clear on read) */ + int_src = dnet_readl(bp, INTR_SRC); + int_enable = dnet_readl(bp, INTR_ENB); + int_current = int_src & int_enable; + + /* restart the queue if we had stopped it for TX fifo almost full */ + if (int_current & DNET_INTR_SRC_TX_FIFOAE) { + int_enable = dnet_readl(bp, INTR_ENB); + int_enable &= ~DNET_INTR_ENB_TX_FIFOAE; + dnet_writel(bp, int_enable, INTR_ENB); + netif_wake_queue(dev); + handled = 1; + } + + /* RX FIFO error checking */ + if (int_current & + (DNET_INTR_SRC_RX_CMDFIFOFF | DNET_INTR_SRC_RX_DATAFIFOFF)) { + printk(KERN_ERR "%s: RX fifo error %x, irq %x\n", __func__, + dnet_readl(bp, RX_STATUS), int_current); + /* we can only flush the RX FIFOs */ + dnet_writel(bp, DNET_SYS_CTL_RXFIFOFLUSH, SYS_CTL); + ndelay(500); + dnet_writel(bp, 0, SYS_CTL); + handled = 1; + } + + /* TX FIFO error checking */ + if (int_current & + (DNET_INTR_SRC_TX_FIFOFULL | DNET_INTR_SRC_TX_DISCFRM)) { + printk(KERN_ERR "%s: TX fifo error %x, irq %x\n", __func__, + dnet_readl(bp, TX_STATUS), int_current); + /* we can only flush the TX FIFOs */ + dnet_writel(bp, DNET_SYS_CTL_TXFIFOFLUSH, SYS_CTL); + ndelay(500); + dnet_writel(bp, 0, SYS_CTL); + handled = 1; + } + + if (int_current & DNET_INTR_SRC_RX_CMDFIFOAF) { + if (netif_rx_schedule_prep(&bp->napi)) { + /* + * There's no point taking any more interrupts + * until we have processed the buffers + */ + /* Disable Rx interrupts and schedule NAPI poll */ + int_enable = dnet_readl(bp, INTR_ENB); + int_enable &= ~DNET_INTR_SRC_RX_CMDFIFOAF; + dnet_writel(bp, int_enable, INTR_ENB); + __netif_rx_schedule(&bp->napi); + } + handled = 1; + } + + if (!handled) + pr_debug("%s: irq %x remains\n", __func__, int_current); + + spin_unlock_irqrestore(&bp->lock, flags); + + return IRQ_RETVAL(handled); +} + +#ifdef DEBUG +static inline void dnet_print_skb(struct sk_buff *skb) +{ + int k; + printk(KERN_DEBUG PFX "data:"); + for (k = 0; k < skb->len; k++) + printk(" %02x", (unsigned int)skb->data[k]); + printk("\n"); +} +#else +#define dnet_print_skb(skb) do {} while (0) +#endif + +static int dnet_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + + struct dnet *bp = netdev_priv(dev); + u32 tx_status, irq_enable; + unsigned int len, i, tx_cmd, wrsz; + unsigned long flags; + unsigned int *bufp; + + tx_status = dnet_readl(bp, TX_STATUS); + + pr_debug("start_xmit: len %u head %p data %p tail %p end %p\n", + skb->len, skb->head, skb->data, skb->tail, skb->end); + dnet_print_skb(skb); + + /* frame size (words) */ + len = (skb->len + 3) >> 2; + + spin_lock_irqsave(&bp->lock, flags); + + tx_status = dnet_readl(bp, TX_STATUS); + + bufp = (unsigned int *)(((u32) skb->data) & 0xFFFFFFFC); + wrsz = (u32) skb->len + 3; + wrsz += ((u32) skb->data) & 0x3; + wrsz >>= 2; + tx_cmd = ((((unsigned int)(skb->data)) & 0x03) << 16) | (u32) skb->len; + + /* check if there is enough room for the current frame */ + if (wrsz < (DNET_FIFO_SIZE - dnet_readl(bp, TX_FIFO_WCNT))) { + for (i = 0; i < wrsz; i++) + dnet_writel(bp, *bufp++, TX_DATA_FIFO); + + /* + * inform MAC that a packet's written and ready to be + * shipped out + */ + dnet_writel(bp, tx_cmd, TX_LEN_FIFO); + } + + if (dnet_readl(bp, TX_FIFO_WCNT) > DNET_FIFO_TX_DATA_AF_TH) { + netif_stop_queue(dev); + tx_status = dnet_readl(bp, INTR_SRC); + irq_enable = dnet_readl(bp, INTR_ENB); + irq_enable |= DNET_INTR_ENB_TX_FIFOAE; + dnet_writel(bp, irq_enable, INTR_ENB); + } + + /* free the buffer */ + dev_kfree_skb(skb); + + spin_unlock_irqrestore(&bp->lock, flags); + + dev->trans_start = jiffies; + + return 0; +} + +static void dnet_reset_hw(struct dnet *bp) +{ + /* put ts_mac in IDLE state i.e. disable rx/tx */ + dnet_writew_mac(bp, DNET_INTERNAL_MODE_REG, DNET_INTERNAL_MODE_FCEN); + + /* + * RX FIFO almost full threshold: only cmd FIFO almost full is + * implemented for RX side + */ + dnet_writel(bp, DNET_FIFO_RX_CMD_AF_TH, RX_FIFO_TH); + /* + * TX FIFO almost empty threshold: only data FIFO almost empty + * is implemented for TX side + */ + dnet_writel(bp, DNET_FIFO_TX_DATA_AE_TH, TX_FIFO_TH); + + /* flush rx/tx fifos */ + dnet_writel(bp, DNET_SYS_CTL_RXFIFOFLUSH | DNET_SYS_CTL_TXFIFOFLUSH, + SYS_CTL); + msleep(1); + dnet_writel(bp, 0, SYS_CTL); +} + +static void dnet_init_hw(struct dnet *bp) +{ + u32 config; + + dnet_reset_hw(bp); + __dnet_set_hwaddr(bp); + + config = dnet_readw_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG); + + if (bp->dev->flags & IFF_PROMISC) + /* Copy All Frames */ + config |= DNET_INTERNAL_RXTX_CONTROL_ENPROMISC; + if (!(bp->dev->flags & IFF_BROADCAST)) + /* No BroadCast */ + config |= DNET_INTERNAL_RXTX_CONTROL_RXMULTICAST; + + config |= DNET_INTERNAL_RXTX_CONTROL_RXPAUSE | + DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST | + DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL | + DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS; + + dnet_writew_mac(bp, DNET_INTERNAL_RXTX_CONTROL_REG, config); + + /* clear irq before enabling them */ + config = dnet_readl(bp, INTR_SRC); + + /* enable RX/TX interrupt, recv packet ready interrupt */ + dnet_writel(bp, DNET_INTR_ENB_GLOBAL_ENABLE | DNET_INTR_ENB_RX_SUMMARY | + DNET_INTR_ENB_TX_SUMMARY | DNET_INTR_ENB_RX_FIFOERR | + DNET_INTR_ENB_RX_ERROR | DNET_INTR_ENB_RX_FIFOFULL | + DNET_INTR_ENB_TX_FIFOFULL | DNET_INTR_ENB_TX_DISCFRM | + DNET_INTR_ENB_RX_PKTRDY, INTR_ENB); +} + +static int dnet_open(struct net_device *dev) +{ + struct dnet *bp = netdev_priv(dev); + + /* if the phy is not yet register, retry later */ + if (!bp->phy_dev) + return -EAGAIN; + + if (!is_valid_ether_addr(dev->dev_addr)) + return -EADDRNOTAVAIL; + + napi_enable(&bp->napi); + dnet_init_hw(bp); + + phy_start_aneg(bp->phy_dev); + + /* schedule a link state check */ + phy_start(bp->phy_dev); + + netif_start_queue(dev); + + return 0; +} + +static int dnet_close(struct net_device *dev) +{ + struct dnet *bp = netdev_priv(dev); + + netif_stop_queue(dev); + napi_disable(&bp->napi); + + if (bp->phy_dev) + phy_stop(bp->phy_dev); + + dnet_reset_hw(bp); + netif_carrier_off(dev); + + return 0; +} + +static inline void dnet_print_pretty_hwstats(struct dnet_stats *hwstat) +{ + pr_debug("%s\n", __func__); + pr_debug("----------------------------- RX statistics " + "-------------------------------\n"); + pr_debug("RX_PKT_IGNR_CNT %-8x\n", hwstat->rx_pkt_ignr); + pr_debug("RX_LEN_CHK_ERR_CNT %-8x\n", hwstat->rx_len_chk_err); + pr_debug("RX_LNG_FRM_CNT %-8x\n", hwstat->rx_lng_frm); + pr_debug("RX_SHRT_FRM_CNT %-8x\n", hwstat->rx_shrt_frm); + pr_debug("RX_IPG_VIOL_CNT %-8x\n", hwstat->rx_ipg_viol); + pr_debug("RX_CRC_ERR_CNT %-8x\n", hwstat->rx_crc_err); + pr_debug("RX_OK_PKT_CNT %-8x\n", hwstat->rx_ok_pkt); + pr_debug("RX_CTL_FRM_CNT %-8x\n", hwstat->rx_ctl_frm); + pr_debug("RX_PAUSE_FRM_CNT %-8x\n", hwstat->rx_pause_frm); + pr_debug("RX_MULTICAST_CNT %-8x\n", hwstat->rx_multicast); + pr_debug("RX_BROADCAST_CNT %-8x\n", hwstat->rx_broadcast); + pr_debug("RX_VLAN_TAG_CNT %-8x\n", hwstat->rx_vlan_tag); + pr_debug("RX_PRE_SHRINK_CNT %-8x\n", hwstat->rx_pre_shrink); + pr_debug("RX_DRIB_NIB_CNT %-8x\n", hwstat->rx_drib_nib); + pr_debug("RX_UNSUP_OPCD_CNT %-8x\n", hwstat->rx_unsup_opcd); + pr_debug("RX_BYTE_CNT %-8x\n", hwstat->rx_byte); + pr_debug("----------------------------- TX statistics " + "-------------------------------\n"); + pr_debug("TX_UNICAST_CNT %-8x\n", hwstat->tx_unicast); + pr_debug("TX_PAUSE_FRM_CNT %-8x\n", hwstat->tx_pause_frm); + pr_debug("TX_MULTICAST_CNT %-8x\n", hwstat->tx_multicast); + pr_debug("TX_BRDCAST_CNT %-8x\n", hwstat->tx_brdcast); + pr_debug("TX_VLAN_TAG_CNT %-8x\n", hwstat->tx_vlan_tag); + pr_debug("TX_BAD_FCS_CNT %-8x\n", hwstat->tx_bad_fcs); + pr_debug("TX_JUMBO_CNT %-8x\n", hwstat->tx_jumbo); + pr_debug("TX_BYTE_CNT %-8x\n", hwstat->tx_byte); +} + +static struct net_device_stats *dnet_get_stats(struct net_device *dev) +{ + + struct dnet *bp = netdev_priv(dev); + struct net_device_stats *nstat = &dev->stats; + struct dnet_stats *hwstat = &bp->hw_stats; + + /* read stats from hardware */ + dnet_update_stats(bp); + + /* Convert HW stats into netdevice stats */ + nstat->rx_errors = (hwstat->rx_len_chk_err + + hwstat->rx_lng_frm + hwstat->rx_shrt_frm + + /* ignore IGP violation error + hwstat->rx_ipg_viol + */ + hwstat->rx_crc_err + + hwstat->rx_pre_shrink + + hwstat->rx_drib_nib + hwstat->rx_unsup_opcd); + nstat->tx_errors = hwstat->tx_bad_fcs; + nstat->rx_length_errors = (hwstat->rx_len_chk_err + + hwstat->rx_lng_frm + + hwstat->rx_shrt_frm + hwstat->rx_pre_shrink); + nstat->rx_crc_errors = hwstat->rx_crc_err; + nstat->rx_frame_errors = hwstat->rx_pre_shrink + hwstat->rx_drib_nib; + nstat->rx_packets = hwstat->rx_ok_pkt; + nstat->tx_packets = (hwstat->tx_unicast + + hwstat->tx_multicast + hwstat->tx_brdcast); + nstat->rx_bytes = hwstat->rx_byte; + nstat->tx_bytes = hwstat->tx_byte; + nstat->multicast = hwstat->rx_multicast; + nstat->rx_missed_errors = hwstat->rx_pkt_ignr; + + dnet_print_pretty_hwstats(hwstat); + + return nstat; +} + +static int dnet_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; + + if (!phydev) + return -ENODEV; + + return phy_ethtool_gset(phydev, cmd); +} + +static int dnet_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; + + if (!phydev) + return -ENODEV; + + return phy_ethtool_sset(phydev, cmd); +} + +static int dnet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) +{ + struct dnet *bp = netdev_priv(dev); + struct phy_device *phydev = bp->phy_dev; + + if (!netif_running(dev)) + return -EINVAL; + + if (!phydev) + return -ENODEV; + + return phy_mii_ioctl(phydev, if_mii(rq), cmd); +} + +static void dnet_get_drvinfo(struct net_device *dev, + struct ethtool_drvinfo *info) +{ + strcpy(info->driver, DRV_NAME); + strcpy(info->version, DRV_VERSION); + strcpy(info->bus_info, "0"); +} + +static const struct ethtool_ops dnet_ethtool_ops = { + .get_settings = dnet_get_settings, + .set_settings = dnet_set_settings, + .get_drvinfo = dnet_get_drvinfo, + .get_link = ethtool_op_get_link, +}; + +static const struct net_device_ops dnet_netdev_ops = { + .ndo_open = dnet_open, + .ndo_stop = dnet_close, + .ndo_get_stats = dnet_get_stats, + .ndo_start_xmit = dnet_start_xmit, + .ndo_do_ioctl = dnet_ioctl, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = eth_change_mtu, +}; + +static int __devinit dnet_probe(struct platform_device *pdev) +{ + struct resource *res; + struct net_device *dev; + struct dnet *bp; + struct phy_device *phydev; + int err = -ENXIO; + unsigned int mem_base, mem_size, irq; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "no mmio resource defined\n"); + goto err_out; + } + mem_base = res->start; + mem_size = resource_size(res); + irq = platform_get_irq(pdev, 0); + + if (!request_mem_region(mem_base, mem_size, DRV_NAME)) { + dev_err(&pdev->dev, "no memory region available\n"); + err = -EBUSY; + goto err_out; + } + + err = -ENOMEM; + dev = alloc_etherdev(sizeof(*bp)); + if (!dev) { + dev_err(&pdev->dev, "etherdev alloc failed, aborting.\n"); + goto err_out; + } + + /* TODO: Actually, we have some interesting features... */ + dev->features |= 0; + + bp = netdev_priv(dev); + bp->dev = dev; + + SET_NETDEV_DEV(dev, &pdev->dev); + + spin_lock_init(&bp->lock); + + bp->regs = ioremap(mem_base, mem_size); + if (!bp->regs) { + dev_err(&pdev->dev, "failed to map registers, aborting.\n"); + err = -ENOMEM; + goto err_out_free_dev; + } + + dev->irq = irq; + err = request_irq(dev->irq, dnet_interrupt, 0, DRV_NAME, dev); + if (err) { + dev_err(&pdev->dev, "Unable to request IRQ %d (error %d)\n", + irq, err); + goto err_out_iounmap; + } + + dev->netdev_ops = &dnet_netdev_ops; + netif_napi_add(dev, &bp->napi, dnet_poll, 64); + dev->ethtool_ops = &dnet_ethtool_ops; + + dev->base_addr = (unsigned long)bp->regs; + + bp->capabilities = dnet_readl(bp, VERCAPS) & DNET_CAPS_MASK; + + dnet_get_hwaddr(bp); + + if (!is_valid_ether_addr(dev->dev_addr)) { + /* choose a random ethernet address */ + random_ether_addr(dev->dev_addr); + __dnet_set_hwaddr(bp); + } + + err = register_netdev(dev); + if (err) { + dev_err(&pdev->dev, "Cannot register net device, aborting.\n"); + goto err_out_free_irq; + } + + /* register the PHY board fixup (for Marvell 88E1111) */ + err = phy_register_fixup_for_uid(0x01410cc0, 0xfffffff0, + dnet_phy_marvell_fixup); + /* we can live without it, so just issue a warning */ + if (err) + dev_warn(&pdev->dev, "Cannot register PHY board fixup.\n"); + + if (dnet_mii_init(bp) != 0) + goto err_out_unregister_netdev; + + dev_info(&pdev->dev, "Dave DNET at 0x%p (0x%08x) irq %d %pM\n", + bp->regs, mem_base, dev->irq, dev->dev_addr); + dev_info(&pdev->dev, "has %smdio, %sirq, %sgigabit, %sdma \n", + (bp->capabilities & DNET_HAS_MDIO) ? "" : "no ", + (bp->capabilities & DNET_HAS_IRQ) ? "" : "no ", + (bp->capabilities & DNET_HAS_GIGABIT) ? "" : "no ", + (bp->capabilities & DNET_HAS_DMA) ? "" : "no "); + phydev = bp->phy_dev; + dev_info(&pdev->dev, "attached PHY driver [%s] " + "(mii_bus:phy_addr=%s, irq=%d)\n", + phydev->drv->name, phydev->dev.bus_id, phydev->irq); + + return 0; + +err_out_unregister_netdev: + unregister_netdev(dev); +err_out_free_irq: + free_irq(dev->irq, dev); +err_out_iounmap: + iounmap(bp->regs); +err_out_free_dev: + free_netdev(dev); +err_out: + return err; +} + +static int __devexit dnet_remove(struct platform_device *pdev) +{ + + struct net_device *dev; + struct dnet *bp; + + dev = platform_get_drvdata(pdev); + + if (dev) { + bp = netdev_priv(dev); + if (bp->phy_dev) + phy_disconnect(bp->phy_dev); + mdiobus_unregister(bp->mii_bus); + kfree(bp->mii_bus->irq); + mdiobus_free(bp->mii_bus); + unregister_netdev(dev); + free_irq(dev->irq, dev); + iounmap(bp->regs); + free_netdev(dev); + } + + return 0; +} + +static struct platform_driver dnet_driver = { + .probe = dnet_probe, + .remove = __devexit_p(dnet_remove), + .driver = { + .name = "dnet", + }, +}; + +static int __init dnet_init(void) +{ + return platform_driver_register(&dnet_driver); +} + +static void __exit dnet_exit(void) +{ + platform_driver_unregister(&dnet_driver); +} + +module_init(dnet_init); +module_exit(dnet_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Dave DNET Ethernet driver"); +MODULE_AUTHOR("Ilya Yanok , " + "Matteo Vit "); diff --git a/drivers/net/dnet.h b/drivers/net/dnet.h new file mode 100644 index 000000000000..37f5b30fa78b --- /dev/null +++ b/drivers/net/dnet.h @@ -0,0 +1,225 @@ +/* + * Dave DNET Ethernet Controller driver + * + * Copyright (C) 2008 Dave S.r.l. + * + * 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 _DNET_H +#define _DNET_H + +#define DRV_NAME "dnet" +#define DRV_VERSION "0.9.1" +#define PFX DRV_NAME ": " + +/* Register access macros */ +#define dnet_writel(port, value, reg) \ + writel((value), (port)->regs + DNET_##reg) +#define dnet_readl(port, reg) readl((port)->regs + DNET_##reg) + +/* ALL DNET FIFO REGISTERS */ +#define DNET_RX_LEN_FIFO 0x000 /* RX_LEN_FIFO */ +#define DNET_RX_DATA_FIFO 0x004 /* RX_DATA_FIFO */ +#define DNET_TX_LEN_FIFO 0x008 /* TX_LEN_FIFO */ +#define DNET_TX_DATA_FIFO 0x00C /* TX_DATA_FIFO */ + +/* ALL DNET CONTROL/STATUS REGISTERS OFFSETS */ +#define DNET_VERCAPS 0x100 /* VERCAPS */ +#define DNET_INTR_SRC 0x104 /* INTR_SRC */ +#define DNET_INTR_ENB 0x108 /* INTR_ENB */ +#define DNET_RX_STATUS 0x10C /* RX_STATUS */ +#define DNET_TX_STATUS 0x110 /* TX_STATUS */ +#define DNET_RX_FRAMES_CNT 0x114 /* RX_FRAMES_CNT */ +#define DNET_TX_FRAMES_CNT 0x118 /* TX_FRAMES_CNT */ +#define DNET_RX_FIFO_TH 0x11C /* RX_FIFO_TH */ +#define DNET_TX_FIFO_TH 0x120 /* TX_FIFO_TH */ +#define DNET_SYS_CTL 0x124 /* SYS_CTL */ +#define DNET_PAUSE_TMR 0x128 /* PAUSE_TMR */ +#define DNET_RX_FIFO_WCNT 0x12C /* RX_FIFO_WCNT */ +#define DNET_TX_FIFO_WCNT 0x130 /* TX_FIFO_WCNT */ + +/* ALL DNET MAC REGISTERS */ +#define DNET_MACREG_DATA 0x200 /* Mac-Reg Data */ +#define DNET_MACREG_ADDR 0x204 /* Mac-Reg Addr */ + +/* ALL DNET RX STATISTICS COUNTERS */ +#define DNET_RX_PKT_IGNR_CNT 0x300 +#define DNET_RX_LEN_CHK_ERR_CNT 0x304 +#define DNET_RX_LNG_FRM_CNT 0x308 +#define DNET_RX_SHRT_FRM_CNT 0x30C +#define DNET_RX_IPG_VIOL_CNT 0x310 +#define DNET_RX_CRC_ERR_CNT 0x314 +#define DNET_RX_OK_PKT_CNT 0x318 +#define DNET_RX_CTL_FRM_CNT 0x31C +#define DNET_RX_PAUSE_FRM_CNT 0x320 +#define DNET_RX_MULTICAST_CNT 0x324 +#define DNET_RX_BROADCAST_CNT 0x328 +#define DNET_RX_VLAN_TAG_CNT 0x32C +#define DNET_RX_PRE_SHRINK_CNT 0x330 +#define DNET_RX_DRIB_NIB_CNT 0x334 +#define DNET_RX_UNSUP_OPCD_CNT 0x338 +#define DNET_RX_BYTE_CNT 0x33C + +/* DNET TX STATISTICS COUNTERS */ +#define DNET_TX_UNICAST_CNT 0x400 +#define DNET_TX_PAUSE_FRM_CNT 0x404 +#define DNET_TX_MULTICAST_CNT 0x408 +#define DNET_TX_BRDCAST_CNT 0x40C +#define DNET_TX_VLAN_TAG_CNT 0x410 +#define DNET_TX_BAD_FCS_CNT 0x414 +#define DNET_TX_JUMBO_CNT 0x418 +#define DNET_TX_BYTE_CNT 0x41C + +/* SOME INTERNAL MAC-CORE REGISTER */ +#define DNET_INTERNAL_MODE_REG 0x0 +#define DNET_INTERNAL_RXTX_CONTROL_REG 0x2 +#define DNET_INTERNAL_MAX_PKT_SIZE_REG 0x4 +#define DNET_INTERNAL_IGP_REG 0x8 +#define DNET_INTERNAL_MAC_ADDR_0_REG 0xa +#define DNET_INTERNAL_MAC_ADDR_1_REG 0xc +#define DNET_INTERNAL_MAC_ADDR_2_REG 0xe +#define DNET_INTERNAL_TX_RX_STS_REG 0x12 +#define DNET_INTERNAL_GMII_MNG_CTL_REG 0x14 +#define DNET_INTERNAL_GMII_MNG_DAT_REG 0x16 + +#define DNET_INTERNAL_GMII_MNG_CMD_FIN (1 << 14) + +#define DNET_INTERNAL_WRITE (1 << 31) + +/* MAC-CORE REGISTER FIELDS */ + +/* MAC-CORE MODE REGISTER FIELDS */ +#define DNET_INTERNAL_MODE_GBITEN (1 << 0) +#define DNET_INTERNAL_MODE_FCEN (1 << 1) +#define DNET_INTERNAL_MODE_RXEN (1 << 2) +#define DNET_INTERNAL_MODE_TXEN (1 << 3) + +/* MAC-CORE RXTX CONTROL REGISTER FIELDS */ +#define DNET_INTERNAL_RXTX_CONTROL_RXSHORTFRAME (1 << 8) +#define DNET_INTERNAL_RXTX_CONTROL_RXBROADCAST (1 << 7) +#define DNET_INTERNAL_RXTX_CONTROL_RXMULTICAST (1 << 4) +#define DNET_INTERNAL_RXTX_CONTROL_RXPAUSE (1 << 3) +#define DNET_INTERNAL_RXTX_CONTROL_DISTXFCS (1 << 2) +#define DNET_INTERNAL_RXTX_CONTROL_DISCFXFCS (1 << 1) +#define DNET_INTERNAL_RXTX_CONTROL_ENPROMISC (1 << 0) +#define DNET_INTERNAL_RXTX_CONTROL_DROPCONTROL (1 << 6) +#define DNET_INTERNAL_RXTX_CONTROL_ENABLEHALFDUP (1 << 5) + +/* SYSTEM CONTROL REGISTER FIELDS */ +#define DNET_SYS_CTL_IGNORENEXTPKT (1 << 0) +#define DNET_SYS_CTL_SENDPAUSE (1 << 2) +#define DNET_SYS_CTL_RXFIFOFLUSH (1 << 3) +#define DNET_SYS_CTL_TXFIFOFLUSH (1 << 4) + +/* TX STATUS REGISTER FIELDS */ +#define DNET_TX_STATUS_FIFO_ALMOST_EMPTY (1 << 2) +#define DNET_TX_STATUS_FIFO_ALMOST_FULL (1 << 1) + +/* INTERRUPT SOURCE REGISTER FIELDS */ +#define DNET_INTR_SRC_TX_PKTSENT (1 << 0) +#define DNET_INTR_SRC_TX_FIFOAF (1 << 1) +#define DNET_INTR_SRC_TX_FIFOAE (1 << 2) +#define DNET_INTR_SRC_TX_DISCFRM (1 << 3) +#define DNET_INTR_SRC_TX_FIFOFULL (1 << 4) +#define DNET_INTR_SRC_RX_CMDFIFOAF (1 << 8) +#define DNET_INTR_SRC_RX_CMDFIFOFF (1 << 9) +#define DNET_INTR_SRC_RX_DATAFIFOFF (1 << 10) +#define DNET_INTR_SRC_TX_SUMMARY (1 << 16) +#define DNET_INTR_SRC_RX_SUMMARY (1 << 17) +#define DNET_INTR_SRC_PHY (1 << 19) + +/* INTERRUPT ENABLE REGISTER FIELDS */ +#define DNET_INTR_ENB_TX_PKTSENT (1 << 0) +#define DNET_INTR_ENB_TX_FIFOAF (1 << 1) +#define DNET_INTR_ENB_TX_FIFOAE (1 << 2) +#define DNET_INTR_ENB_TX_DISCFRM (1 << 3) +#define DNET_INTR_ENB_TX_FIFOFULL (1 << 4) +#define DNET_INTR_ENB_RX_PKTRDY (1 << 8) +#define DNET_INTR_ENB_RX_FIFOAF (1 << 9) +#define DNET_INTR_ENB_RX_FIFOERR (1 << 10) +#define DNET_INTR_ENB_RX_ERROR (1 << 11) +#define DNET_INTR_ENB_RX_FIFOFULL (1 << 12) +#define DNET_INTR_ENB_RX_FIFOAE (1 << 13) +#define DNET_INTR_ENB_TX_SUMMARY (1 << 16) +#define DNET_INTR_ENB_RX_SUMMARY (1 << 17) +#define DNET_INTR_ENB_GLOBAL_ENABLE (1 << 18) + +/* default values: + * almost empty = less than one full sized ethernet frame (no jumbo) inside + * the fifo almost full = can write less than one full sized ethernet frame + * (no jumbo) inside the fifo + */ +#define DNET_CFG_TX_FIFO_FULL_THRES 25 +#define DNET_CFG_RX_FIFO_FULL_THRES 20 + +/* + * Capabilities. Used by the driver to know the capabilities that the ethernet + * controller inside the FPGA have. + */ + +#define DNET_HAS_MDIO (1 << 0) +#define DNET_HAS_IRQ (1 << 1) +#define DNET_HAS_GIGABIT (1 << 2) +#define DNET_HAS_DMA (1 << 3) + +#define DNET_HAS_MII (1 << 4) /* or GMII */ +#define DNET_HAS_RMII (1 << 5) /* or RGMII */ + +#define DNET_CAPS_MASK 0xFFFF + +#define DNET_FIFO_SIZE 1024 /* 1K x 32 bit */ +#define DNET_FIFO_TX_DATA_AF_TH (DNET_FIFO_SIZE - 384) /* 384 = 1536 / 4 */ +#define DNET_FIFO_TX_DATA_AE_TH 384 + +#define DNET_FIFO_RX_CMD_AF_TH (1 << 16) /* just one frame inside the FIFO */ + +/* + * Hardware-collected statistics. + */ +struct dnet_stats { + u32 rx_pkt_ignr; + u32 rx_len_chk_err; + u32 rx_lng_frm; + u32 rx_shrt_frm; + u32 rx_ipg_viol; + u32 rx_crc_err; + u32 rx_ok_pkt; + u32 rx_ctl_frm; + u32 rx_pause_frm; + u32 rx_multicast; + u32 rx_broadcast; + u32 rx_vlan_tag; + u32 rx_pre_shrink; + u32 rx_drib_nib; + u32 rx_unsup_opcd; + u32 rx_byte; + u32 tx_unicast; + u32 tx_pause_frm; + u32 tx_multicast; + u32 tx_brdcast; + u32 tx_vlan_tag; + u32 tx_bad_fcs; + u32 tx_jumbo; + u32 tx_byte; +}; + +struct dnet { + void __iomem *regs; + spinlock_t lock; + struct platform_device *pdev; + struct net_device *dev; + struct dnet_stats hw_stats; + unsigned int capabilities; /* read from FPGA */ + struct napi_struct napi; + + /* PHY stuff */ + struct mii_bus *mii_bus; + struct phy_device *phy_dev; + unsigned int link; + unsigned int speed; + unsigned int duplex; +}; + +#endif /* _DNET_H */ -- cgit v1.2.3 From 2c5849ea38fdad477d72dcf1c8c4842db4b33aae Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Wed, 11 Mar 2009 23:28:57 -0700 Subject: dnet: Fix warnings on 64-bit. Signed-off-by: David S. Miller --- drivers/net/dnet.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c index 92c3bd3a4721..4b96974fe76e 100644 --- a/drivers/net/dnet.c +++ b/drivers/net/dnet.c @@ -553,8 +553,8 @@ static int dnet_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_status = dnet_readl(bp, TX_STATUS); - pr_debug("start_xmit: len %u head %p data %p tail %p end %p\n", - skb->len, skb->head, skb->data, skb->tail, skb->end); + pr_debug("start_xmit: len %u head %p data %p\n", + skb->len, skb->head, skb->data); dnet_print_skb(skb); /* frame size (words) */ @@ -564,11 +564,11 @@ static int dnet_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_status = dnet_readl(bp, TX_STATUS); - bufp = (unsigned int *)(((u32) skb->data) & 0xFFFFFFFC); + bufp = (unsigned int *)(((unsigned long) skb->data) & ~0x3UL); wrsz = (u32) skb->len + 3; - wrsz += ((u32) skb->data) & 0x3; + wrsz += ((unsigned long) skb->data) & 0x3; wrsz >>= 2; - tx_cmd = ((((unsigned int)(skb->data)) & 0x03) << 16) | (u32) skb->len; + tx_cmd = ((((unsigned long)(skb->data)) & 0x03) << 16) | (u32) skb->len; /* check if there is enough room for the current frame */ if (wrsz < (DNET_FIFO_SIZE - dnet_readl(bp, TX_FIFO_WCNT))) { -- cgit v1.2.3 From 6b7c5b947c671a96e39f9526a5fd70c178b8dfd1 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Wed, 11 Mar 2009 23:32:03 -0700 Subject: net: Add be2net driver. Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- MAINTAINERS | 9 + drivers/net/Kconfig | 2 + drivers/net/Makefile | 1 + drivers/net/benet/Kconfig | 7 + drivers/net/benet/Makefile | 7 + drivers/net/benet/be.h | 327 +++++++ drivers/net/benet/be_cmds.c | 861 ++++++++++++++++++ drivers/net/benet/be_cmds.h | 688 +++++++++++++++ drivers/net/benet/be_ethtool.c | 362 ++++++++ drivers/net/benet/be_hw.h | 211 +++++ drivers/net/benet/be_main.c | 1903 ++++++++++++++++++++++++++++++++++++++++ 11 files changed, 4378 insertions(+) create mode 100644 drivers/net/benet/Kconfig create mode 100644 drivers/net/benet/Makefile create mode 100644 drivers/net/benet/be.h create mode 100644 drivers/net/benet/be_cmds.c create mode 100644 drivers/net/benet/be_cmds.h create mode 100644 drivers/net/benet/be_ethtool.c create mode 100644 drivers/net/benet/be_hw.h create mode 100644 drivers/net/benet/be_main.c (limited to 'drivers') diff --git a/MAINTAINERS b/MAINTAINERS index 1c2ca1dc66f2..43934437511b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3880,6 +3880,15 @@ L: linux-ide@vger.kernel.org T: git kernel.org:/pub/scm/linux/kernel/git/jgarzik/libata-dev.git S: Supported +SERVER ENGINES 10Gbps NIC - BladeEngine 2 DRIVER +P: Sathya Perla +M: sathyap@serverengines.com +P: Subbu Seetharaman +M: subbus@serverengines.com +L: netdev@vger.kernel.org +W: http://www.serverengines.com +S: Supported + SFC NETWORK DRIVER P: Steve Hodgson P: Ben Hutchings diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 5c28b06dac6e..435e2e3a82c8 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2630,6 +2630,8 @@ config QLGE source "drivers/net/sfc/Kconfig" +source "drivers/net/benet/Kconfig" + endif # NETDEV_10000 source "drivers/net/tokenring/Kconfig" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 6d9bba58b9a4..471baaff229f 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_GIANFAR) += gianfar_driver.o obj-$(CONFIG_TEHUTI) += tehuti.o obj-$(CONFIG_ENIC) += enic/ obj-$(CONFIG_JME) += jme.o +obj-$(CONFIG_BE2NET) += benet/ gianfar_driver-objs := gianfar.o \ gianfar_ethtool.o \ diff --git a/drivers/net/benet/Kconfig b/drivers/net/benet/Kconfig new file mode 100644 index 000000000000..c6934f179c09 --- /dev/null +++ b/drivers/net/benet/Kconfig @@ -0,0 +1,7 @@ +config BE2NET + tristate "ServerEngines' 10Gbps NIC - BladeEngine 2" + depends on PCI && INET + select INET_LRO + help + This driver implements the NIC functionality for ServerEngines' + 10Gbps network adapter - BladeEngine 2. diff --git a/drivers/net/benet/Makefile b/drivers/net/benet/Makefile new file mode 100644 index 000000000000..a60cd8051135 --- /dev/null +++ b/drivers/net/benet/Makefile @@ -0,0 +1,7 @@ +# +# Makefile to build the network driver for ServerEngine's BladeEngine. +# + +obj-$(CONFIG_BE2NET) += be2net.o + +be2net-y := be_main.o be_cmds.o be_ethtool.o diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h new file mode 100644 index 000000000000..63d593d53153 --- /dev/null +++ b/drivers/net/benet/be.h @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * All rights reserved. + * + * 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. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +#ifndef BE_H +#define BE_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "be_hw.h" + +#define DRV_VER "2.0.348" +#define DRV_NAME "be2net" +#define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" +#define DRV_DESC BE_NAME "Driver" + +/* Number of bytes of an RX frame that are copied to skb->data */ +#define BE_HDR_LEN 64 +#define BE_MAX_JUMBO_FRAME_SIZE 9018 +#define BE_MIN_MTU 256 + +#define BE_NUM_VLANS_SUPPORTED 64 +#define BE_MAX_EQD 96 +#define BE_MAX_TX_FRAG_COUNT 30 + +#define EVNT_Q_LEN 1024 +#define TX_Q_LEN 2048 +#define TX_CQ_LEN 1024 +#define RX_Q_LEN 1024 /* Does not support any other value */ +#define RX_CQ_LEN 1024 +#define MCC_Q_LEN 64 /* total size not to exceed 8 pages */ +#define MCC_CQ_LEN 256 + +#define BE_NAPI_WEIGHT 64 +#define MAX_RX_POST BE_NAPI_WEIGHT /* Frags posted at a time */ +#define RX_FRAGS_REFILL_WM (RX_Q_LEN - MAX_RX_POST) + +#define BE_MAX_LRO_DESCRIPTORS 16 +#define BE_MAX_FRAGS_PER_FRAME 16 + +struct be_dma_mem { + void *va; + dma_addr_t dma; + u32 size; +}; + +struct be_queue_info { + struct be_dma_mem dma_mem; + u16 len; + u16 entry_size; /* Size of an element in the queue */ + u16 id; + u16 tail, head; + bool created; + atomic_t used; /* Number of valid elements in the queue */ +}; + +struct be_ctrl_info { + u8 __iomem *csr; + u8 __iomem *db; /* Door Bell */ + u8 __iomem *pcicfg; /* PCI config space */ + int pci_func; + + /* Mbox used for cmd request/response */ + spinlock_t cmd_lock; /* For serializing cmds to BE card */ + struct be_dma_mem mbox_mem; + /* Mbox mem is adjusted to align to 16 bytes. The allocated addr + * is stored for freeing purpose */ + struct be_dma_mem mbox_mem_alloced; +}; + +#include "be_cmds.h" + +struct be_drvr_stats { + u32 be_tx_reqs; /* number of TX requests initiated */ + u32 be_tx_stops; /* number of times TX Q was stopped */ + u32 be_fwd_reqs; /* number of send reqs through forwarding i/f */ + u32 be_tx_wrbs; /* number of tx WRBs used */ + u32 be_tx_events; /* number of tx completion events */ + u32 be_tx_compl; /* number of tx completion entries processed */ + u64 be_tx_jiffies; + ulong be_tx_bytes; + ulong be_tx_bytes_prev; + u32 be_tx_rate; + + u32 cache_barrier[16]; + + u32 be_ethrx_post_fail;/* number of ethrx buffer alloc failures */ + u32 be_polls; /* number of times NAPI called poll function */ + u32 be_rx_events; /* number of ucast rx completion events */ + u32 be_rx_compl; /* number of rx completion entries processed */ + u32 be_lro_hgram_data[8]; /* histogram of LRO data packets */ + u32 be_lro_hgram_ack[8]; /* histogram of LRO ACKs */ + u64 be_rx_jiffies; + ulong be_rx_bytes; + ulong be_rx_bytes_prev; + u32 be_rx_rate; + /* number of non ether type II frames dropped where + * frame len > length field of Mac Hdr */ + u32 be_802_3_dropped_frames; + /* number of non ether type II frames malformed where + * in frame len < length field of Mac Hdr */ + u32 be_802_3_malformed_frames; + u32 be_rxcp_err; /* Num rx completion entries w/ err set. */ + ulong rx_fps_jiffies; /* jiffies at last FPS calc */ + u32 be_rx_frags; + u32 be_prev_rx_frags; + u32 be_rx_fps; /* Rx frags per second */ +}; + +struct be_stats_obj { + struct be_drvr_stats drvr_stats; + struct net_device_stats net_stats; + struct be_dma_mem cmd; +}; + +struct be_eq_obj { + struct be_queue_info q; + char desc[32]; + + /* Adaptive interrupt coalescing (AIC) info */ + bool enable_aic; + u16 min_eqd; /* in usecs */ + u16 max_eqd; /* in usecs */ + u16 cur_eqd; /* in usecs */ + + struct napi_struct napi; +}; + +struct be_tx_obj { + struct be_queue_info q; + struct be_queue_info cq; + /* Remember the skbs that were transmitted */ + struct sk_buff *sent_skb_list[TX_Q_LEN]; +}; + +/* Struct to remember the pages posted for rx frags */ +struct be_rx_page_info { + struct page *page; + dma_addr_t bus; + u16 page_offset; + bool last_page_user; +}; + +struct be_rx_obj { + struct be_queue_info q; + struct be_queue_info cq; + struct be_rx_page_info page_info_tbl[RX_Q_LEN]; + struct net_lro_mgr lro_mgr; + struct net_lro_desc lro_desc[BE_MAX_LRO_DESCRIPTORS]; +}; + +#define BE_NUM_MSIX_VECTORS 2 /* 1 each for Tx and Rx */ +struct be_adapter { + struct pci_dev *pdev; + struct net_device *netdev; + + /* Mbox, pci config, csr address information */ + struct be_ctrl_info ctrl; + + struct msix_entry msix_entries[BE_NUM_MSIX_VECTORS]; + bool msix_enabled; + bool isr_registered; + + /* TX Rings */ + struct be_eq_obj tx_eq; + struct be_tx_obj tx_obj; + + u32 cache_line_break[8]; + + /* Rx rings */ + struct be_eq_obj rx_eq; + struct be_rx_obj rx_obj; + u32 big_page_size; /* Compounded page size shared by rx wrbs */ + + struct vlan_group *vlan_grp; + u16 num_vlans; + u8 vlan_tag[VLAN_GROUP_ARRAY_LEN]; + + struct be_stats_obj stats; + /* Work queue used to perform periodic tasks like getting statistics */ + struct delayed_work work; + + /* Ethtool knobs and info */ + bool rx_csum; /* BE card must perform rx-checksumming */ + u32 max_rx_coal; + char fw_ver[FW_VER_LEN]; + u32 if_handle; /* Used to configure filtering */ + u32 pmac_id; /* MAC addr handle used by BE card */ + + struct be_link_info link; + u32 port_num; +}; + +extern struct ethtool_ops be_ethtool_ops; + +#define drvr_stats(adapter) (&adapter->stats.drvr_stats) + +#define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) + +static inline u32 MODULO(u16 val, u16 limit) +{ + BUG_ON(limit & (limit - 1)); + return val & (limit - 1); +} + +static inline void index_adv(u16 *index, u16 val, u16 limit) +{ + *index = MODULO((*index + val), limit); +} + +static inline void index_inc(u16 *index, u16 limit) +{ + *index = MODULO((*index + 1), limit); +} + +#define PAGE_SHIFT_4K 12 +#define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K) + +/* Returns number of pages spanned by the data starting at the given addr */ +#define PAGES_4K_SPANNED(_address, size) \ + ((u32)((((size_t)(_address) & (PAGE_SIZE_4K - 1)) + \ + (size) + (PAGE_SIZE_4K - 1)) >> PAGE_SHIFT_4K)) + +/* Byte offset into the page corresponding to given address */ +#define OFFSET_IN_PAGE(addr) \ + ((size_t)(addr) & (PAGE_SIZE_4K-1)) + +/* Returns bit offset within a DWORD of a bitfield */ +#define AMAP_BIT_OFFSET(_struct, field) \ + (((size_t)&(((_struct *)0)->field))%32) + +/* Returns the bit mask of the field that is NOT shifted into location. */ +static inline u32 amap_mask(u32 bitsize) +{ + return (bitsize == 32 ? 0xFFFFFFFF : (1 << bitsize) - 1); +} + +static inline void +amap_set(void *ptr, u32 dw_offset, u32 mask, u32 offset, u32 value) +{ + u32 *dw = (u32 *) ptr + dw_offset; + *dw &= ~(mask << offset); + *dw |= (mask & value) << offset; +} + +#define AMAP_SET_BITS(_struct, field, ptr, val) \ + amap_set(ptr, \ + offsetof(_struct, field)/32, \ + amap_mask(sizeof(((_struct *)0)->field)), \ + AMAP_BIT_OFFSET(_struct, field), \ + val) + +static inline u32 amap_get(void *ptr, u32 dw_offset, u32 mask, u32 offset) +{ + u32 *dw = (u32 *) ptr; + return mask & (*(dw + dw_offset) >> offset); +} + +#define AMAP_GET_BITS(_struct, field, ptr) \ + amap_get(ptr, \ + offsetof(_struct, field)/32, \ + amap_mask(sizeof(((_struct *)0)->field)), \ + AMAP_BIT_OFFSET(_struct, field)) + +#define be_dws_cpu_to_le(wrb, len) swap_dws(wrb, len) +#define be_dws_le_to_cpu(wrb, len) swap_dws(wrb, len) +static inline void swap_dws(void *wrb, int len) +{ +#ifdef __BIG_ENDIAN + u32 *dw = wrb; + BUG_ON(len % 4); + do { + *dw = cpu_to_le32(*dw); + dw++; + len -= 4; + } while (len); +#endif /* __BIG_ENDIAN */ +} + +static inline u8 is_tcp_pkt(struct sk_buff *skb) +{ + u8 val = 0; + + if (ip_hdr(skb)->version == 4) + val = (ip_hdr(skb)->protocol == IPPROTO_TCP); + else if (ip_hdr(skb)->version == 6) + val = (ipv6_hdr(skb)->nexthdr == NEXTHDR_TCP); + + return val; +} + +static inline u8 is_udp_pkt(struct sk_buff *skb) +{ + u8 val = 0; + + if (ip_hdr(skb)->version == 4) + val = (ip_hdr(skb)->protocol == IPPROTO_UDP); + else if (ip_hdr(skb)->version == 6) + val = (ipv6_hdr(skb)->nexthdr == NEXTHDR_UDP); + + return val; +} + +#endif /* BE_H */ diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c new file mode 100644 index 000000000000..d444aed962bc --- /dev/null +++ b/drivers/net/benet/be_cmds.c @@ -0,0 +1,861 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * All rights reserved. + * + * 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. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +#include "be.h" + +static int be_mbox_db_ready_wait(void __iomem *db) +{ + int cnt = 0, wait = 5; + u32 ready; + + do { + ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK; + if (ready) + break; + + if (cnt > 200000) { + printk(KERN_WARNING DRV_NAME + ": mbox_db poll timed out\n"); + return -1; + } + + if (cnt > 50) + wait = 200; + cnt += wait; + udelay(wait); + } while (true); + + return 0; +} + +/* + * Insert the mailbox address into the doorbell in two steps + */ +static int be_mbox_db_ring(struct be_ctrl_info *ctrl) +{ + int status; + u16 compl_status, extd_status; + u32 val = 0; + void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET; + struct be_dma_mem *mbox_mem = &ctrl->mbox_mem; + struct be_mcc_mailbox *mbox = mbox_mem->va; + struct be_mcc_cq_entry *cqe = &mbox->cqe; + + memset(cqe, 0, sizeof(*cqe)); + + val &= ~MPU_MAILBOX_DB_RDY_MASK; + val |= MPU_MAILBOX_DB_HI_MASK; + /* at bits 2 - 31 place mbox dma addr msb bits 34 - 63 */ + val |= (upper_32_bits(mbox_mem->dma) >> 2) << 2; + iowrite32(val, db); + + /* wait for ready to be set */ + status = be_mbox_db_ready_wait(db); + if (status != 0) + return status; + + val = 0; + val &= ~MPU_MAILBOX_DB_RDY_MASK; + val &= ~MPU_MAILBOX_DB_HI_MASK; + /* at bits 2 - 31 place mbox dma addr lsb bits 4 - 33 */ + val |= (u32)(mbox_mem->dma >> 4) << 2; + iowrite32(val, db); + + status = be_mbox_db_ready_wait(db); + if (status != 0) + return status; + + /* compl entry has been made now */ + be_dws_le_to_cpu(cqe, sizeof(*cqe)); + if (!(cqe->flags & CQE_FLAGS_VALID_MASK)) { + printk(KERN_WARNING DRV_NAME ": ERROR invalid mbox compl\n"); + return -1; + } + + compl_status = (cqe->status >> CQE_STATUS_COMPL_SHIFT) & + CQE_STATUS_COMPL_MASK; + if (compl_status != MCC_STATUS_SUCCESS) { + extd_status = (cqe->status >> CQE_STATUS_EXTD_SHIFT) & + CQE_STATUS_EXTD_MASK; + printk(KERN_WARNING DRV_NAME + ": ERROR in cmd compl. status(compl/extd)=%d/%d\n", + compl_status, extd_status); + } + + return compl_status; +} + +static int be_POST_stage_get(struct be_ctrl_info *ctrl, u16 *stage) +{ + u32 sem = ioread32(ctrl->csr + MPU_EP_SEMAPHORE_OFFSET); + + *stage = sem & EP_SEMAPHORE_POST_STAGE_MASK; + if ((sem >> EP_SEMAPHORE_POST_ERR_SHIFT) & EP_SEMAPHORE_POST_ERR_MASK) + return -1; + else + return 0; +} + +static int be_POST_stage_poll(struct be_ctrl_info *ctrl, u16 poll_stage) +{ + u16 stage, cnt, error; + for (cnt = 0; cnt < 5000; cnt++) { + error = be_POST_stage_get(ctrl, &stage); + if (error) + return -1; + + if (stage == poll_stage) + break; + udelay(1000); + } + if (stage != poll_stage) + return -1; + return 0; +} + + +int be_cmd_POST(struct be_ctrl_info *ctrl) +{ + u16 stage, error; + + error = be_POST_stage_get(ctrl, &stage); + if (error) + goto err; + + if (stage == POST_STAGE_ARMFW_RDY) + return 0; + + if (stage != POST_STAGE_AWAITING_HOST_RDY) + goto err; + + /* On awaiting host rdy, reset and again poll on awaiting host rdy */ + iowrite32(POST_STAGE_BE_RESET, ctrl->csr + MPU_EP_SEMAPHORE_OFFSET); + error = be_POST_stage_poll(ctrl, POST_STAGE_AWAITING_HOST_RDY); + if (error) + goto err; + + /* Now kickoff POST and poll on armfw ready */ + iowrite32(POST_STAGE_HOST_RDY, ctrl->csr + MPU_EP_SEMAPHORE_OFFSET); + error = be_POST_stage_poll(ctrl, POST_STAGE_ARMFW_RDY); + if (error) + goto err; + + return 0; +err: + printk(KERN_WARNING DRV_NAME ": ERROR, stage=%d\n", stage); + return -1; +} + +static inline void *embedded_payload(struct be_mcc_wrb *wrb) +{ + return wrb->payload.embedded_payload; +} + +static inline struct be_sge *nonembedded_sgl(struct be_mcc_wrb *wrb) +{ + return &wrb->payload.sgl[0]; +} + +/* Don't touch the hdr after it's prepared */ +static void be_wrb_hdr_prepare(struct be_mcc_wrb *wrb, int payload_len, + bool embedded, u8 sge_cnt) +{ + if (embedded) + wrb->embedded |= MCC_WRB_EMBEDDED_MASK; + else + wrb->embedded |= (sge_cnt & MCC_WRB_SGE_CNT_MASK) << + MCC_WRB_SGE_CNT_SHIFT; + wrb->payload_length = payload_len; + be_dws_cpu_to_le(wrb, 20); +} + +/* Don't touch the hdr after it's prepared */ +static void be_cmd_hdr_prepare(struct be_cmd_req_hdr *req_hdr, + u8 subsystem, u8 opcode, int cmd_len) +{ + req_hdr->opcode = opcode; + req_hdr->subsystem = subsystem; + req_hdr->request_length = cpu_to_le32(cmd_len - sizeof(*req_hdr)); +} + +static void be_cmd_page_addrs_prepare(struct phys_addr *pages, u32 max_pages, + struct be_dma_mem *mem) +{ + int i, buf_pages = min(PAGES_4K_SPANNED(mem->va, mem->size), max_pages); + u64 dma = (u64)mem->dma; + + for (i = 0; i < buf_pages; i++) { + pages[i].lo = cpu_to_le32(dma & 0xFFFFFFFF); + pages[i].hi = cpu_to_le32(upper_32_bits(dma)); + dma += PAGE_SIZE_4K; + } +} + +/* Converts interrupt delay in microseconds to multiplier value */ +static u32 eq_delay_to_mult(u32 usec_delay) +{ +#define MAX_INTR_RATE 651042 + const u32 round = 10; + u32 multiplier; + + if (usec_delay == 0) + multiplier = 0; + else { + u32 interrupt_rate = 1000000 / usec_delay; + /* Max delay, corresponding to the lowest interrupt rate */ + if (interrupt_rate == 0) + multiplier = 1023; + else { + multiplier = (MAX_INTR_RATE - interrupt_rate) * round; + multiplier /= interrupt_rate; + /* Round the multiplier to the closest value.*/ + multiplier = (multiplier + round/2) / round; + multiplier = min(multiplier, (u32)1023); + } + } + return multiplier; +} + +static inline struct be_mcc_wrb *wrb_from_mbox(struct be_dma_mem *mbox_mem) +{ + return &((struct be_mcc_mailbox *)(mbox_mem->va))->wrb; +} + +int be_cmd_eq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *eq, int eq_delay) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_eq_create *req = embedded_payload(wrb); + struct be_cmd_resp_eq_create *resp = embedded_payload(wrb); + struct be_dma_mem *q_mem = &eq->dma_mem; + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_EQ_CREATE, sizeof(*req)); + + req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); + + AMAP_SET_BITS(struct amap_eq_context, func, req->context, + ctrl->pci_func); + AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); + /* 4byte eqe*/ + AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); + AMAP_SET_BITS(struct amap_eq_context, count, req->context, + __ilog2_u32(eq->len/256)); + AMAP_SET_BITS(struct amap_eq_context, delaymult, req->context, + eq_delay_to_mult(eq_delay)); + be_dws_cpu_to_le(req->context, sizeof(req->context)); + + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + + status = be_mbox_db_ring(ctrl); + if (!status) { + eq->id = le16_to_cpu(resp->eq_id); + eq->created = true; + } + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr, + u8 type, bool permanent, u32 if_handle) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_mac_query *req = embedded_payload(wrb); + struct be_cmd_resp_mac_query *resp = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_MAC_QUERY, sizeof(*req)); + + req->type = type; + if (permanent) { + req->permanent = 1; + } else { + req->if_id = cpu_to_le16((u16)if_handle); + req->permanent = 0; + } + + status = be_mbox_db_ring(ctrl); + if (!status) + memcpy(mac_addr, resp->mac.addr, ETH_ALEN); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr, + u32 if_id, u32 *pmac_id) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_pmac_add *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req)); + + req->if_id = cpu_to_le32(if_id); + memcpy(req->mac_address, mac_addr, ETH_ALEN); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_pmac_add *resp = embedded_payload(wrb); + *pmac_id = le32_to_cpu(resp->pmac_id); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_pmac_del *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req)); + + req->if_id = cpu_to_le32(if_id); + req->pmac_id = cpu_to_le32(pmac_id); + + status = be_mbox_db_ring(ctrl); + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +int be_cmd_cq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *cq, struct be_queue_info *eq, + bool sol_evts, bool no_delay, int coalesce_wm) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_cq_create *req = embedded_payload(wrb); + struct be_cmd_resp_cq_create *resp = embedded_payload(wrb); + struct be_dma_mem *q_mem = &cq->dma_mem; + void *ctxt = &req->context; + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_CQ_CREATE, sizeof(*req)); + + req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); + + AMAP_SET_BITS(struct amap_cq_context, coalescwm, ctxt, coalesce_wm); + AMAP_SET_BITS(struct amap_cq_context, nodelay, ctxt, no_delay); + AMAP_SET_BITS(struct amap_cq_context, count, ctxt, + __ilog2_u32(cq->len/256)); + AMAP_SET_BITS(struct amap_cq_context, valid, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context, solevent, ctxt, sol_evts); + AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); + AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); + AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 0); + AMAP_SET_BITS(struct amap_cq_context, func, ctxt, ctrl->pci_func); + be_dws_cpu_to_le(ctxt, sizeof(req->context)); + + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + + status = be_mbox_db_ring(ctrl); + if (!status) { + cq->id = le16_to_cpu(resp->cq_id); + cq->created = true; + } + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +int be_cmd_txq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *txq, + struct be_queue_info *cq) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_eth_tx_create *req = embedded_payload(wrb); + struct be_dma_mem *q_mem = &txq->dma_mem; + void *ctxt = &req->context; + int status; + u32 len_encoded; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_TX_CREATE, + sizeof(*req)); + + req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); + req->ulp_num = BE_ULP1_NUM; + req->type = BE_ETH_TX_RING_TYPE_STANDARD; + + len_encoded = fls(txq->len); /* log2(len) + 1 */ + if (len_encoded == 16) + len_encoded = 0; + AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt, len_encoded); + AMAP_SET_BITS(struct amap_tx_context, pci_func_id, ctxt, + ctrl->pci_func); + AMAP_SET_BITS(struct amap_tx_context, ctx_valid, ctxt, 1); + AMAP_SET_BITS(struct amap_tx_context, cq_id_send, ctxt, cq->id); + + be_dws_cpu_to_le(ctxt, sizeof(req->context)); + + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_eth_tx_create *resp = embedded_payload(wrb); + txq->id = le16_to_cpu(resp->cid); + txq->created = true; + } + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +int be_cmd_rxq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *rxq, u16 cq_id, u16 frag_size, + u16 max_frame_size, u32 if_id, u32 rss) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_eth_rx_create *req = embedded_payload(wrb); + struct be_dma_mem *q_mem = &rxq->dma_mem; + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_RX_CREATE, + sizeof(*req)); + + req->cq_id = cpu_to_le16(cq_id); + req->frag_size = fls(frag_size) - 1; + req->num_pages = 2; + be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); + req->interface_id = cpu_to_le32(if_id); + req->max_frame_size = cpu_to_le16(max_frame_size); + req->rss_queue = cpu_to_le32(rss); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_eth_rx_create *resp = embedded_payload(wrb); + rxq->id = le16_to_cpu(resp->id); + rxq->created = true; + } + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +/* Generic destroyer function for all types of queues */ +int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, + int queue_type) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_q_destroy *req = embedded_payload(wrb); + u8 subsys = 0, opcode = 0; + int status; + + spin_lock(&ctrl->cmd_lock); + + memset(wrb, 0, sizeof(*wrb)); + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + switch (queue_type) { + case QTYPE_EQ: + subsys = CMD_SUBSYSTEM_COMMON; + opcode = OPCODE_COMMON_EQ_DESTROY; + break; + case QTYPE_CQ: + subsys = CMD_SUBSYSTEM_COMMON; + opcode = OPCODE_COMMON_CQ_DESTROY; + break; + case QTYPE_TXQ: + subsys = CMD_SUBSYSTEM_ETH; + opcode = OPCODE_ETH_TX_DESTROY; + break; + case QTYPE_RXQ: + subsys = CMD_SUBSYSTEM_ETH; + opcode = OPCODE_ETH_RX_DESTROY; + break; + default: + printk(KERN_WARNING DRV_NAME ":bad Q type in Q destroy cmd\n"); + status = -1; + goto err; + } + be_cmd_hdr_prepare(&req->hdr, subsys, opcode, sizeof(*req)); + req->id = cpu_to_le16(q->id); + + status = be_mbox_db_ring(ctrl); +err: + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +/* Create an rx filtering policy configuration on an i/f */ +int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 flags, u8 *mac, + bool pmac_invalid, u32 *if_handle, u32 *pmac_id) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_if_create *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req)); + + req->capability_flags = cpu_to_le32(flags); + req->enable_flags = cpu_to_le32(flags); + if (!pmac_invalid) + memcpy(req->mac_addr, mac, ETH_ALEN); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_if_create *resp = embedded_payload(wrb); + *if_handle = le32_to_cpu(resp->interface_id); + if (!pmac_invalid) + *pmac_id = le32_to_cpu(resp->pmac_id); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 interface_id) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_if_destroy *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_INTERFACE_DESTROY, sizeof(*req)); + + req->interface_id = cpu_to_le32(interface_id); + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + + return status; +} + +/* Get stats is a non embedded command: the request is not embedded inside + * WRB but is a separate dma memory block + */ +int be_cmd_get_stats(struct be_ctrl_info *ctrl, struct be_dma_mem *nonemb_cmd) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_get_stats *req = nonemb_cmd->va; + struct be_sge *sge = nonembedded_sgl(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + memset(req, 0, sizeof(*req)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), false, 1); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, + OPCODE_ETH_GET_STATISTICS, sizeof(*req)); + sge->pa_hi = cpu_to_le32(upper_32_bits(nonemb_cmd->dma)); + sge->pa_lo = cpu_to_le32(nonemb_cmd->dma & 0xFFFFFFFF); + sge->len = cpu_to_le32(nonemb_cmd->size); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_get_stats *resp = nonemb_cmd->va; + be_dws_le_to_cpu(&resp->hw_stats, sizeof(resp->hw_stats)); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_link_status_query(struct be_ctrl_info *ctrl, + struct be_link_info *link) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_link_status *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_LINK_STATUS_QUERY, sizeof(*req)); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_link_status *resp = embedded_payload(wrb); + link->speed = resp->mac_speed; + link->duplex = resp->mac_duplex; + link->fault = resp->mac_fault; + } else { + link->speed = PHY_LINK_SPEED_ZERO; + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_get_fw_version *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_FW_VERSION, sizeof(*req)); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_get_fw_version *resp = embedded_payload(wrb); + strncpy(fw_ver, resp->firmware_version_string, FW_VER_LEN); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +/* set the EQ delay interval of an EQ to specified value */ +int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_modify_eq_delay *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_MODIFY_EQ_DELAY, sizeof(*req)); + + req->num_eq = cpu_to_le32(1); + req->delay[0].eq_id = cpu_to_le32(eq_id); + req->delay[0].phase = 0; + req->delay[0].delay_multiplier = cpu_to_le32(eqd); + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, u16 *vtag_array, + u32 num, bool untagged, bool promiscuous) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_vlan_config *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_VLAN_CONFIG, sizeof(*req)); + + req->interface_id = if_id; + req->promiscuous = promiscuous; + req->untagged = untagged; + req->num_vlan = num; + if (!promiscuous) { + memcpy(req->normal_vlan, vtag_array, + req->num_vlan * sizeof(vtag_array[0])); + } + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, u8 port_num, bool en) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_promiscuous_config *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, + OPCODE_ETH_PROMISCUOUS, sizeof(*req)); + + if (port_num) + req->port1_promiscuous = en; + else + req->port0_promiscuous = en; + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, u8 *mac_table, + u32 num, bool promiscuous) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_mcast_mac_config *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_NTWK_MULTICAST_SET, sizeof(*req)); + + req->interface_id = if_id; + req->promiscuous = promiscuous; + if (!promiscuous) { + req->num_mac = cpu_to_le16(num); + if (num) + memcpy(req->mac, mac_table, ETH_ALEN * num); + } + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, u32 tx_fc, u32 rx_fc) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_set_flow_control *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_SET_FLOW_CONTROL, sizeof(*req)); + + req->tx_flow_control = cpu_to_le16((u16)tx_fc); + req->rx_flow_control = cpu_to_le16((u16)rx_fc); + + status = be_mbox_db_ring(ctrl); + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, u32 *tx_fc, u32 *rx_fc) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_get_flow_control *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_GET_FLOW_CONTROL, sizeof(*req)); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_get_flow_control *resp = + embedded_payload(wrb); + *tx_fc = le16_to_cpu(resp->tx_flow_control); + *rx_fc = le16_to_cpu(resp->rx_flow_control); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} + +int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num) +{ + struct be_mcc_wrb *wrb = wrb_from_mbox(&ctrl->mbox_mem); + struct be_cmd_req_query_fw_cfg *req = embedded_payload(wrb); + int status; + + spin_lock(&ctrl->cmd_lock); + + memset(wrb, 0, sizeof(*wrb)); + + be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0); + + be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON, + OPCODE_COMMON_QUERY_FIRMWARE_CONFIG, sizeof(*req)); + + status = be_mbox_db_ring(ctrl); + if (!status) { + struct be_cmd_resp_query_fw_cfg *resp = embedded_payload(wrb); + *port_num = le32_to_cpu(resp->phys_port); + } + + spin_unlock(&ctrl->cmd_lock); + return status; +} diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h new file mode 100644 index 000000000000..e499e2d5b8c3 --- /dev/null +++ b/drivers/net/benet/be_cmds.h @@ -0,0 +1,688 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * All rights reserved. + * + * 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. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +/* + * The driver sends configuration and managements command requests to the + * firmware in the BE. These requests are communicated to the processor + * using Work Request Blocks (WRBs) submitted to the MCC-WRB ring or via one + * WRB inside a MAILBOX. + * The commands are serviced by the ARM processor in the BladeEngine's MPU. + */ + +struct be_sge { + u32 pa_lo; + u32 pa_hi; + u32 len; +}; + +#define MCC_WRB_EMBEDDED_MASK 1 /* bit 0 of dword 0*/ +#define MCC_WRB_SGE_CNT_SHIFT 3 /* bits 3 - 7 of dword 0 */ +#define MCC_WRB_SGE_CNT_MASK 0x1F /* bits 3 - 7 of dword 0 */ +struct be_mcc_wrb { + u32 embedded; /* dword 0 */ + u32 payload_length; /* dword 1 */ + u32 tag0; /* dword 2 */ + u32 tag1; /* dword 3 */ + u32 rsvd; /* dword 4 */ + union { + u8 embedded_payload[236]; /* used by embedded cmds */ + struct be_sge sgl[19]; /* used by non-embedded cmds */ + } payload; +}; + +#define CQE_FLAGS_VALID_MASK (1 << 31) +#define CQE_FLAGS_ASYNC_MASK (1 << 30) +#define CQE_FLAGS_COMPLETED_MASK (1 << 28) +#define CQE_FLAGS_CONSUMED_MASK (1 << 27) + +/* Completion Status */ +enum { + MCC_STATUS_SUCCESS = 0x0, +/* The client does not have sufficient privileges to execute the command */ + MCC_STATUS_INSUFFICIENT_PRIVILEGES = 0x1, +/* A parameter in the command was invalid. */ + MCC_STATUS_INVALID_PARAMETER = 0x2, +/* There are insufficient chip resources to execute the command */ + MCC_STATUS_INSUFFICIENT_RESOURCES = 0x3, +/* The command is completing because the queue was getting flushed */ + MCC_STATUS_QUEUE_FLUSHING = 0x4, +/* The command is completing with a DMA error */ + MCC_STATUS_DMA_FAILED = 0x5 +}; + +#define CQE_STATUS_COMPL_MASK 0xFFFF +#define CQE_STATUS_COMPL_SHIFT 0 /* bits 0 - 15 */ +#define CQE_STATUS_EXTD_MASK 0xFFFF +#define CQE_STATUS_EXTD_SHIFT 0 /* bits 0 - 15 */ + +struct be_mcc_cq_entry { + u32 status; /* dword 0 */ + u32 tag0; /* dword 1 */ + u32 tag1; /* dword 2 */ + u32 flags; /* dword 3 */ +}; + +struct be_mcc_mailbox { + struct be_mcc_wrb wrb; + struct be_mcc_cq_entry cqe; +}; + +#define CMD_SUBSYSTEM_COMMON 0x1 +#define CMD_SUBSYSTEM_ETH 0x3 + +#define OPCODE_COMMON_NTWK_MAC_QUERY 1 +#define OPCODE_COMMON_NTWK_MAC_SET 2 +#define OPCODE_COMMON_NTWK_MULTICAST_SET 3 +#define OPCODE_COMMON_NTWK_VLAN_CONFIG 4 +#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY 5 +#define OPCODE_COMMON_CQ_CREATE 12 +#define OPCODE_COMMON_EQ_CREATE 13 +#define OPCODE_COMMON_MCC_CREATE 21 +#define OPCODE_COMMON_NTWK_RX_FILTER 34 +#define OPCODE_COMMON_GET_FW_VERSION 35 +#define OPCODE_COMMON_SET_FLOW_CONTROL 36 +#define OPCODE_COMMON_GET_FLOW_CONTROL 37 +#define OPCODE_COMMON_SET_FRAME_SIZE 39 +#define OPCODE_COMMON_MODIFY_EQ_DELAY 41 +#define OPCODE_COMMON_FIRMWARE_CONFIG 42 +#define OPCODE_COMMON_NTWK_INTERFACE_CREATE 50 +#define OPCODE_COMMON_NTWK_INTERFACE_DESTROY 51 +#define OPCODE_COMMON_CQ_DESTROY 54 +#define OPCODE_COMMON_EQ_DESTROY 55 +#define OPCODE_COMMON_QUERY_FIRMWARE_CONFIG 58 +#define OPCODE_COMMON_NTWK_PMAC_ADD 59 +#define OPCODE_COMMON_NTWK_PMAC_DEL 60 + +#define OPCODE_ETH_ACPI_CONFIG 2 +#define OPCODE_ETH_PROMISCUOUS 3 +#define OPCODE_ETH_GET_STATISTICS 4 +#define OPCODE_ETH_TX_CREATE 7 +#define OPCODE_ETH_RX_CREATE 8 +#define OPCODE_ETH_TX_DESTROY 9 +#define OPCODE_ETH_RX_DESTROY 10 + +struct be_cmd_req_hdr { + u8 opcode; /* dword 0 */ + u8 subsystem; /* dword 0 */ + u8 port_number; /* dword 0 */ + u8 domain; /* dword 0 */ + u32 timeout; /* dword 1 */ + u32 request_length; /* dword 2 */ + u32 rsvd; /* dword 3 */ +}; + +#define RESP_HDR_INFO_OPCODE_SHIFT 0 /* bits 0 - 7 */ +#define RESP_HDR_INFO_SUBSYS_SHIFT 8 /* bits 8 - 15 */ +struct be_cmd_resp_hdr { + u32 info; /* dword 0 */ + u32 status; /* dword 1 */ + u32 response_length; /* dword 2 */ + u32 actual_resp_len; /* dword 3 */ +}; + +struct phys_addr { + u32 lo; + u32 hi; +}; + +/************************** + * BE Command definitions * + **************************/ + +/* Pseudo amap definition in which each bit of the actual structure is defined + * as a byte: used to calculate offset/shift/mask of each field */ +struct amap_eq_context { + u8 cidx[13]; /* dword 0*/ + u8 rsvd0[3]; /* dword 0*/ + u8 epidx[13]; /* dword 0*/ + u8 valid; /* dword 0*/ + u8 rsvd1; /* dword 0*/ + u8 size; /* dword 0*/ + u8 pidx[13]; /* dword 1*/ + u8 rsvd2[3]; /* dword 1*/ + u8 pd[10]; /* dword 1*/ + u8 count[3]; /* dword 1*/ + u8 solevent; /* dword 1*/ + u8 stalled; /* dword 1*/ + u8 armed; /* dword 1*/ + u8 rsvd3[4]; /* dword 2*/ + u8 func[8]; /* dword 2*/ + u8 rsvd4; /* dword 2*/ + u8 delaymult[10]; /* dword 2*/ + u8 rsvd5[2]; /* dword 2*/ + u8 phase[2]; /* dword 2*/ + u8 nodelay; /* dword 2*/ + u8 rsvd6[4]; /* dword 2*/ + u8 rsvd7[32]; /* dword 3*/ +} __packed; + +struct be_cmd_req_eq_create { + struct be_cmd_req_hdr hdr; + u16 num_pages; /* sword */ + u16 rsvd0; /* sword */ + u8 context[sizeof(struct amap_eq_context) / 8]; + struct phys_addr pages[8]; +} __packed; + +struct be_cmd_resp_eq_create { + struct be_cmd_resp_hdr resp_hdr; + u16 eq_id; /* sword */ + u16 rsvd0; /* sword */ +} __packed; + +/******************** Mac query ***************************/ +enum { + MAC_ADDRESS_TYPE_STORAGE = 0x0, + MAC_ADDRESS_TYPE_NETWORK = 0x1, + MAC_ADDRESS_TYPE_PD = 0x2, + MAC_ADDRESS_TYPE_MANAGEMENT = 0x3 +}; + +struct mac_addr { + u16 size_of_struct; + u8 addr[ETH_ALEN]; +} __packed; + +struct be_cmd_req_mac_query { + struct be_cmd_req_hdr hdr; + u8 type; + u8 permanent; + u16 if_id; +} __packed; + +struct be_cmd_resp_mac_query { + struct be_cmd_resp_hdr hdr; + struct mac_addr mac; +}; + +/******************** PMac Add ***************************/ +struct be_cmd_req_pmac_add { + struct be_cmd_req_hdr hdr; + u32 if_id; + u8 mac_address[ETH_ALEN]; + u8 rsvd0[2]; +} __packed; + +struct be_cmd_resp_pmac_add { + struct be_cmd_resp_hdr hdr; + u32 pmac_id; +}; + +/******************** PMac Del ***************************/ +struct be_cmd_req_pmac_del { + struct be_cmd_req_hdr hdr; + u32 if_id; + u32 pmac_id; +}; + +/******************** Create CQ ***************************/ +/* Pseudo amap definition in which each bit of the actual structure is defined + * as a byte: used to calculate offset/shift/mask of each field */ +struct amap_cq_context { + u8 cidx[11]; /* dword 0*/ + u8 rsvd0; /* dword 0*/ + u8 coalescwm[2]; /* dword 0*/ + u8 nodelay; /* dword 0*/ + u8 epidx[11]; /* dword 0*/ + u8 rsvd1; /* dword 0*/ + u8 count[2]; /* dword 0*/ + u8 valid; /* dword 0*/ + u8 solevent; /* dword 0*/ + u8 eventable; /* dword 0*/ + u8 pidx[11]; /* dword 1*/ + u8 rsvd2; /* dword 1*/ + u8 pd[10]; /* dword 1*/ + u8 eqid[8]; /* dword 1*/ + u8 stalled; /* dword 1*/ + u8 armed; /* dword 1*/ + u8 rsvd3[4]; /* dword 2*/ + u8 func[8]; /* dword 2*/ + u8 rsvd4[20]; /* dword 2*/ + u8 rsvd5[32]; /* dword 3*/ +} __packed; + +struct be_cmd_req_cq_create { + struct be_cmd_req_hdr hdr; + u16 num_pages; + u16 rsvd0; + u8 context[sizeof(struct amap_cq_context) / 8]; + struct phys_addr pages[8]; +} __packed; + +struct be_cmd_resp_cq_create { + struct be_cmd_resp_hdr hdr; + u16 cq_id; + u16 rsvd0; +} __packed; + +/******************** Create TxQ ***************************/ +#define BE_ETH_TX_RING_TYPE_STANDARD 2 +#define BE_ULP1_NUM 1 + +/* Pseudo amap definition in which each bit of the actual structure is defined + * as a byte: used to calculate offset/shift/mask of each field */ +struct amap_tx_context { + u8 rsvd0[16]; /* dword 0 */ + u8 tx_ring_size[4]; /* dword 0 */ + u8 rsvd1[26]; /* dword 0 */ + u8 pci_func_id[8]; /* dword 1 */ + u8 rsvd2[9]; /* dword 1 */ + u8 ctx_valid; /* dword 1 */ + u8 cq_id_send[16]; /* dword 2 */ + u8 rsvd3[16]; /* dword 2 */ + u8 rsvd4[32]; /* dword 3 */ + u8 rsvd5[32]; /* dword 4 */ + u8 rsvd6[32]; /* dword 5 */ + u8 rsvd7[32]; /* dword 6 */ + u8 rsvd8[32]; /* dword 7 */ + u8 rsvd9[32]; /* dword 8 */ + u8 rsvd10[32]; /* dword 9 */ + u8 rsvd11[32]; /* dword 10 */ + u8 rsvd12[32]; /* dword 11 */ + u8 rsvd13[32]; /* dword 12 */ + u8 rsvd14[32]; /* dword 13 */ + u8 rsvd15[32]; /* dword 14 */ + u8 rsvd16[32]; /* dword 15 */ +} __packed; + +struct be_cmd_req_eth_tx_create { + struct be_cmd_req_hdr hdr; + u8 num_pages; + u8 ulp_num; + u8 type; + u8 bound_port; + u8 context[sizeof(struct amap_tx_context) / 8]; + struct phys_addr pages[8]; +} __packed; + +struct be_cmd_resp_eth_tx_create { + struct be_cmd_resp_hdr hdr; + u16 cid; + u16 rsvd0; +} __packed; + +/******************** Create RxQ ***************************/ +struct be_cmd_req_eth_rx_create { + struct be_cmd_req_hdr hdr; + u16 cq_id; + u8 frag_size; + u8 num_pages; + struct phys_addr pages[2]; + u32 interface_id; + u16 max_frame_size; + u16 rsvd0; + u32 rss_queue; +} __packed; + +struct be_cmd_resp_eth_rx_create { + struct be_cmd_resp_hdr hdr; + u16 id; + u8 cpu_id; + u8 rsvd0; +} __packed; + +/******************** Q Destroy ***************************/ +/* Type of Queue to be destroyed */ +enum { + QTYPE_EQ = 1, + QTYPE_CQ, + QTYPE_TXQ, + QTYPE_RXQ +}; + +struct be_cmd_req_q_destroy { + struct be_cmd_req_hdr hdr; + u16 id; + u16 bypass_flush; /* valid only for rx q destroy */ +} __packed; + +/************ I/f Create (it's actually I/f Config Create)**********/ + +/* Capability flags for the i/f */ +enum be_if_flags { + BE_IF_FLAGS_RSS = 0x4, + BE_IF_FLAGS_PROMISCUOUS = 0x8, + BE_IF_FLAGS_BROADCAST = 0x10, + BE_IF_FLAGS_UNTAGGED = 0x20, + BE_IF_FLAGS_ULP = 0x40, + BE_IF_FLAGS_VLAN_PROMISCUOUS = 0x80, + BE_IF_FLAGS_VLAN = 0x100, + BE_IF_FLAGS_MCAST_PROMISCUOUS = 0x200, + BE_IF_FLAGS_PASS_L2_ERRORS = 0x400, + BE_IF_FLAGS_PASS_L3L4_ERRORS = 0x800 +}; + +/* An RX interface is an object with one or more MAC addresses and + * filtering capabilities. */ +struct be_cmd_req_if_create { + struct be_cmd_req_hdr hdr; + u32 version; /* ignore currntly */ + u32 capability_flags; + u32 enable_flags; + u8 mac_addr[ETH_ALEN]; + u8 rsvd0; + u8 pmac_invalid; /* if set, don't attach the mac addr to the i/f */ + u32 vlan_tag; /* not used currently */ +} __packed; + +struct be_cmd_resp_if_create { + struct be_cmd_resp_hdr hdr; + u32 interface_id; + u32 pmac_id; +}; + +/****** I/f Destroy(it's actually I/f Config Destroy )**********/ +struct be_cmd_req_if_destroy { + struct be_cmd_req_hdr hdr; + u32 interface_id; +}; + +/*************** HW Stats Get **********************************/ +struct be_port_rxf_stats { + u32 rx_bytes_lsd; /* dword 0*/ + u32 rx_bytes_msd; /* dword 1*/ + u32 rx_total_frames; /* dword 2*/ + u32 rx_unicast_frames; /* dword 3*/ + u32 rx_multicast_frames; /* dword 4*/ + u32 rx_broadcast_frames; /* dword 5*/ + u32 rx_crc_errors; /* dword 6*/ + u32 rx_alignment_symbol_errors; /* dword 7*/ + u32 rx_pause_frames; /* dword 8*/ + u32 rx_control_frames; /* dword 9*/ + u32 rx_in_range_errors; /* dword 10*/ + u32 rx_out_range_errors; /* dword 11*/ + u32 rx_frame_too_long; /* dword 12*/ + u32 rx_address_match_errors; /* dword 13*/ + u32 rx_vlan_mismatch; /* dword 14*/ + u32 rx_dropped_too_small; /* dword 15*/ + u32 rx_dropped_too_short; /* dword 16*/ + u32 rx_dropped_header_too_small; /* dword 17*/ + u32 rx_dropped_tcp_length; /* dword 18*/ + u32 rx_dropped_runt; /* dword 19*/ + u32 rx_64_byte_packets; /* dword 20*/ + u32 rx_65_127_byte_packets; /* dword 21*/ + u32 rx_128_256_byte_packets; /* dword 22*/ + u32 rx_256_511_byte_packets; /* dword 23*/ + u32 rx_512_1023_byte_packets; /* dword 24*/ + u32 rx_1024_1518_byte_packets; /* dword 25*/ + u32 rx_1519_2047_byte_packets; /* dword 26*/ + u32 rx_2048_4095_byte_packets; /* dword 27*/ + u32 rx_4096_8191_byte_packets; /* dword 28*/ + u32 rx_8192_9216_byte_packets; /* dword 29*/ + u32 rx_ip_checksum_errs; /* dword 30*/ + u32 rx_tcp_checksum_errs; /* dword 31*/ + u32 rx_udp_checksum_errs; /* dword 32*/ + u32 rx_non_rss_packets; /* dword 33*/ + u32 rx_ipv4_packets; /* dword 34*/ + u32 rx_ipv6_packets; /* dword 35*/ + u32 rx_ipv4_bytes_lsd; /* dword 36*/ + u32 rx_ipv4_bytes_msd; /* dword 37*/ + u32 rx_ipv6_bytes_lsd; /* dword 38*/ + u32 rx_ipv6_bytes_msd; /* dword 39*/ + u32 rx_chute1_packets; /* dword 40*/ + u32 rx_chute2_packets; /* dword 41*/ + u32 rx_chute3_packets; /* dword 42*/ + u32 rx_management_packets; /* dword 43*/ + u32 rx_switched_unicast_packets; /* dword 44*/ + u32 rx_switched_multicast_packets; /* dword 45*/ + u32 rx_switched_broadcast_packets; /* dword 46*/ + u32 tx_bytes_lsd; /* dword 47*/ + u32 tx_bytes_msd; /* dword 48*/ + u32 tx_unicastframes; /* dword 49*/ + u32 tx_multicastframes; /* dword 50*/ + u32 tx_broadcastframes; /* dword 51*/ + u32 tx_pauseframes; /* dword 52*/ + u32 tx_controlframes; /* dword 53*/ + u32 tx_64_byte_packets; /* dword 54*/ + u32 tx_65_127_byte_packets; /* dword 55*/ + u32 tx_128_256_byte_packets; /* dword 56*/ + u32 tx_256_511_byte_packets; /* dword 57*/ + u32 tx_512_1023_byte_packets; /* dword 58*/ + u32 tx_1024_1518_byte_packets; /* dword 59*/ + u32 tx_1519_2047_byte_packets; /* dword 60*/ + u32 tx_2048_4095_byte_packets; /* dword 61*/ + u32 tx_4096_8191_byte_packets; /* dword 62*/ + u32 tx_8192_9216_byte_packets; /* dword 63*/ + u32 rx_fifo_overflow; /* dword 64*/ + u32 rx_input_fifo_overflow; /* dword 65*/ +}; + +struct be_rxf_stats { + struct be_port_rxf_stats port[2]; + u32 rx_drops_no_pbuf; /* dword 132*/ + u32 rx_drops_no_txpb; /* dword 133*/ + u32 rx_drops_no_erx_descr; /* dword 134*/ + u32 rx_drops_no_tpre_descr; /* dword 135*/ + u32 management_rx_port_packets; /* dword 136*/ + u32 management_rx_port_bytes; /* dword 137*/ + u32 management_rx_port_pause_frames; /* dword 138*/ + u32 management_rx_port_errors; /* dword 139*/ + u32 management_tx_port_packets; /* dword 140*/ + u32 management_tx_port_bytes; /* dword 141*/ + u32 management_tx_port_pause; /* dword 142*/ + u32 management_rx_port_rxfifo_overflow; /* dword 143*/ + u32 rx_drops_too_many_frags; /* dword 144*/ + u32 rx_drops_invalid_ring; /* dword 145*/ + u32 forwarded_packets; /* dword 146*/ + u32 rx_drops_mtu; /* dword 147*/ + u32 rsvd0[15]; +}; + +struct be_erx_stats { + u32 rx_drops_no_fragments[44]; /* dwordS 0 to 43*/ + u32 debug_wdma_sent_hold; /* dword 44*/ + u32 debug_wdma_pbfree_sent_hold; /* dword 45*/ + u32 debug_wdma_zerobyte_pbfree_sent_hold; /* dword 46*/ + u32 debug_pmem_pbuf_dealloc; /* dword 47*/ +}; + +struct be_hw_stats { + struct be_rxf_stats rxf; + u32 rsvd[48]; + struct be_erx_stats erx; +}; + +struct be_cmd_req_get_stats { + struct be_cmd_req_hdr hdr; + u8 rsvd[sizeof(struct be_hw_stats)]; +}; + +struct be_cmd_resp_get_stats { + struct be_cmd_resp_hdr hdr; + struct be_hw_stats hw_stats; +}; + +struct be_cmd_req_vlan_config { + struct be_cmd_req_hdr hdr; + u8 interface_id; + u8 promiscuous; + u8 untagged; + u8 num_vlan; + u16 normal_vlan[64]; +} __packed; + +struct be_cmd_req_promiscuous_config { + struct be_cmd_req_hdr hdr; + u8 port0_promiscuous; + u8 port1_promiscuous; + u16 rsvd0; +} __packed; + +struct macaddr { + u8 byte[ETH_ALEN]; +}; + +struct be_cmd_req_mcast_mac_config { + struct be_cmd_req_hdr hdr; + u16 num_mac; + u8 promiscuous; + u8 interface_id; + struct macaddr mac[32]; +} __packed; + +static inline struct be_hw_stats * +hw_stats_from_cmd(struct be_cmd_resp_get_stats *cmd) +{ + return &cmd->hw_stats; +} + +/******************** Link Status Query *******************/ +struct be_cmd_req_link_status { + struct be_cmd_req_hdr hdr; + u32 rsvd; +}; + +struct be_link_info { + u8 duplex; + u8 speed; + u8 fault; +}; + +enum { + PHY_LINK_DUPLEX_NONE = 0x0, + PHY_LINK_DUPLEX_HALF = 0x1, + PHY_LINK_DUPLEX_FULL = 0x2 +}; + +enum { + PHY_LINK_SPEED_ZERO = 0x0, /* => No link */ + PHY_LINK_SPEED_10MBPS = 0x1, + PHY_LINK_SPEED_100MBPS = 0x2, + PHY_LINK_SPEED_1GBPS = 0x3, + PHY_LINK_SPEED_10GBPS = 0x4 +}; + +struct be_cmd_resp_link_status { + struct be_cmd_resp_hdr hdr; + u8 physical_port; + u8 mac_duplex; + u8 mac_speed; + u8 mac_fault; + u8 mgmt_mac_duplex; + u8 mgmt_mac_speed; + u16 rsvd0; +} __packed; + +/******************** Get FW Version *******************/ +#define FW_VER_LEN 32 +struct be_cmd_req_get_fw_version { + struct be_cmd_req_hdr hdr; + u8 rsvd0[FW_VER_LEN]; + u8 rsvd1[FW_VER_LEN]; +} __packed; + +struct be_cmd_resp_get_fw_version { + struct be_cmd_resp_hdr hdr; + u8 firmware_version_string[FW_VER_LEN]; + u8 fw_on_flash_version_string[FW_VER_LEN]; +} __packed; + +/******************** Set Flow Contrl *******************/ +struct be_cmd_req_set_flow_control { + struct be_cmd_req_hdr hdr; + u16 tx_flow_control; + u16 rx_flow_control; +} __packed; + +/******************** Get Flow Contrl *******************/ +struct be_cmd_req_get_flow_control { + struct be_cmd_req_hdr hdr; + u32 rsvd; +}; + +struct be_cmd_resp_get_flow_control { + struct be_cmd_resp_hdr hdr; + u16 tx_flow_control; + u16 rx_flow_control; +} __packed; + +/******************** Modify EQ Delay *******************/ +struct be_cmd_req_modify_eq_delay { + struct be_cmd_req_hdr hdr; + u32 num_eq; + struct { + u32 eq_id; + u32 phase; + u32 delay_multiplier; + } delay[8]; +} __packed; + +struct be_cmd_resp_modify_eq_delay { + struct be_cmd_resp_hdr hdr; + u32 rsvd0; +} __packed; + +/******************** Get FW Config *******************/ +struct be_cmd_req_query_fw_cfg { + struct be_cmd_req_hdr hdr; + u32 rsvd[30]; +}; + +struct be_cmd_resp_query_fw_cfg { + struct be_cmd_resp_hdr hdr; + u32 be_config_number; + u32 asic_revision; + u32 phys_port; + u32 function_mode; + u32 rsvd[26]; +}; + +extern int be_pci_fnum_get(struct be_ctrl_info *ctrl); +extern int be_cmd_POST(struct be_ctrl_info *ctrl); +extern int be_cmd_mac_addr_query(struct be_ctrl_info *ctrl, u8 *mac_addr, + u8 type, bool permanent, u32 if_handle); +extern int be_cmd_pmac_add(struct be_ctrl_info *ctrl, u8 *mac_addr, + u32 if_id, u32 *pmac_id); +extern int be_cmd_pmac_del(struct be_ctrl_info *ctrl, u32 if_id, u32 pmac_id); +extern int be_cmd_if_create(struct be_ctrl_info *ctrl, u32 if_flags, u8 *mac, + bool pmac_invalid, u32 *if_handle, u32 *pmac_id); +extern int be_cmd_if_destroy(struct be_ctrl_info *ctrl, u32 if_handle); +extern int be_cmd_eq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *eq, int eq_delay); +extern int be_cmd_cq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *cq, struct be_queue_info *eq, + bool sol_evts, bool no_delay, + int num_cqe_dma_coalesce); +extern int be_cmd_txq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *txq, + struct be_queue_info *cq); +extern int be_cmd_rxq_create(struct be_ctrl_info *ctrl, + struct be_queue_info *rxq, u16 cq_id, + u16 frag_size, u16 max_frame_size, u32 if_id, + u32 rss); +extern int be_cmd_q_destroy(struct be_ctrl_info *ctrl, struct be_queue_info *q, + int type); +extern int be_cmd_link_status_query(struct be_ctrl_info *ctrl, + struct be_link_info *link); +extern int be_cmd_reset(struct be_ctrl_info *ctrl); +extern int be_cmd_get_stats(struct be_ctrl_info *ctrl, + struct be_dma_mem *nonemb_cmd); +extern int be_cmd_get_fw_ver(struct be_ctrl_info *ctrl, char *fw_ver); + +extern int be_cmd_modify_eqd(struct be_ctrl_info *ctrl, u32 eq_id, u32 eqd); +extern int be_cmd_vlan_config(struct be_ctrl_info *ctrl, u32 if_id, + u16 *vtag_array, u32 num, bool untagged, + bool promiscuous); +extern int be_cmd_promiscuous_config(struct be_ctrl_info *ctrl, + u8 port_num, bool en); +extern int be_cmd_mcast_mac_set(struct be_ctrl_info *ctrl, u32 if_id, + u8 *mac_table, u32 num, bool promiscuous); +extern int be_cmd_set_flow_control(struct be_ctrl_info *ctrl, + u32 tx_fc, u32 rx_fc); +extern int be_cmd_get_flow_control(struct be_ctrl_info *ctrl, + u32 *tx_fc, u32 *rx_fc); +extern int be_cmd_query_fw_cfg(struct be_ctrl_info *ctrl, u32 *port_num); diff --git a/drivers/net/benet/be_ethtool.c b/drivers/net/benet/be_ethtool.c new file mode 100644 index 000000000000..04f4b73fa8d8 --- /dev/null +++ b/drivers/net/benet/be_ethtool.c @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * All rights reserved. + * + * 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. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +#include "be.h" +#include + +struct be_ethtool_stat { + char desc[ETH_GSTRING_LEN]; + int type; + int size; + int offset; +}; + +enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT, ERXSTAT}; +#define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \ + offsetof(_struct, field) +#define NETSTAT_INFO(field) #field, NETSTAT,\ + FIELDINFO(struct net_device_stats,\ + field) +#define DRVSTAT_INFO(field) #field, DRVSTAT,\ + FIELDINFO(struct be_drvr_stats, field) +#define MISCSTAT_INFO(field) #field, MISCSTAT,\ + FIELDINFO(struct be_rxf_stats, field) +#define PORTSTAT_INFO(field) #field, PORTSTAT,\ + FIELDINFO(struct be_port_rxf_stats, \ + field) +#define ERXSTAT_INFO(field) #field, ERXSTAT,\ + FIELDINFO(struct be_erx_stats, field) + +static const struct be_ethtool_stat et_stats[] = { + {NETSTAT_INFO(rx_packets)}, + {NETSTAT_INFO(tx_packets)}, + {NETSTAT_INFO(rx_bytes)}, + {NETSTAT_INFO(tx_bytes)}, + {NETSTAT_INFO(rx_errors)}, + {NETSTAT_INFO(tx_errors)}, + {NETSTAT_INFO(rx_dropped)}, + {NETSTAT_INFO(tx_dropped)}, + {DRVSTAT_INFO(be_tx_reqs)}, + {DRVSTAT_INFO(be_tx_stops)}, + {DRVSTAT_INFO(be_fwd_reqs)}, + {DRVSTAT_INFO(be_tx_wrbs)}, + {DRVSTAT_INFO(be_polls)}, + {DRVSTAT_INFO(be_tx_events)}, + {DRVSTAT_INFO(be_rx_events)}, + {DRVSTAT_INFO(be_tx_compl)}, + {DRVSTAT_INFO(be_rx_compl)}, + {DRVSTAT_INFO(be_ethrx_post_fail)}, + {DRVSTAT_INFO(be_802_3_dropped_frames)}, + {DRVSTAT_INFO(be_802_3_malformed_frames)}, + {DRVSTAT_INFO(be_tx_rate)}, + {DRVSTAT_INFO(be_rx_rate)}, + {PORTSTAT_INFO(rx_unicast_frames)}, + {PORTSTAT_INFO(rx_multicast_frames)}, + {PORTSTAT_INFO(rx_broadcast_frames)}, + {PORTSTAT_INFO(rx_crc_errors)}, + {PORTSTAT_INFO(rx_alignment_symbol_errors)}, + {PORTSTAT_INFO(rx_pause_frames)}, + {PORTSTAT_INFO(rx_control_frames)}, + {PORTSTAT_INFO(rx_in_range_errors)}, + {PORTSTAT_INFO(rx_out_range_errors)}, + {PORTSTAT_INFO(rx_frame_too_long)}, + {PORTSTAT_INFO(rx_address_match_errors)}, + {PORTSTAT_INFO(rx_vlan_mismatch)}, + {PORTSTAT_INFO(rx_dropped_too_small)}, + {PORTSTAT_INFO(rx_dropped_too_short)}, + {PORTSTAT_INFO(rx_dropped_header_too_small)}, + {PORTSTAT_INFO(rx_dropped_tcp_length)}, + {PORTSTAT_INFO(rx_dropped_runt)}, + {PORTSTAT_INFO(rx_fifo_overflow)}, + {PORTSTAT_INFO(rx_input_fifo_overflow)}, + {PORTSTAT_INFO(rx_ip_checksum_errs)}, + {PORTSTAT_INFO(rx_tcp_checksum_errs)}, + {PORTSTAT_INFO(rx_udp_checksum_errs)}, + {PORTSTAT_INFO(rx_non_rss_packets)}, + {PORTSTAT_INFO(rx_ipv4_packets)}, + {PORTSTAT_INFO(rx_ipv6_packets)}, + {PORTSTAT_INFO(tx_unicastframes)}, + {PORTSTAT_INFO(tx_multicastframes)}, + {PORTSTAT_INFO(tx_broadcastframes)}, + {PORTSTAT_INFO(tx_pauseframes)}, + {PORTSTAT_INFO(tx_controlframes)}, + {MISCSTAT_INFO(rx_drops_no_pbuf)}, + {MISCSTAT_INFO(rx_drops_no_txpb)}, + {MISCSTAT_INFO(rx_drops_no_erx_descr)}, + {MISCSTAT_INFO(rx_drops_no_tpre_descr)}, + {MISCSTAT_INFO(rx_drops_too_many_frags)}, + {MISCSTAT_INFO(rx_drops_invalid_ring)}, + {MISCSTAT_INFO(forwarded_packets)}, + {MISCSTAT_INFO(rx_drops_mtu)}, + {ERXSTAT_INFO(rx_drops_no_fragments)}, +}; +#define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats) + +static void +be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + strcpy(drvinfo->driver, DRV_NAME); + strcpy(drvinfo->version, DRV_VER); + strncpy(drvinfo->fw_version, adapter->fw_ver, FW_VER_LEN); + strcpy(drvinfo->bus_info, pci_name(adapter->pdev)); + drvinfo->testinfo_len = 0; + drvinfo->regdump_len = 0; + drvinfo->eedump_len = 0; +} + +static int +be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + + coalesce->rx_max_coalesced_frames = adapter->max_rx_coal; + + coalesce->rx_coalesce_usecs = rx_eq->cur_eqd; + coalesce->rx_coalesce_usecs_high = rx_eq->max_eqd; + coalesce->rx_coalesce_usecs_low = rx_eq->min_eqd; + + coalesce->tx_coalesce_usecs = tx_eq->cur_eqd; + coalesce->tx_coalesce_usecs_high = tx_eq->max_eqd; + coalesce->tx_coalesce_usecs_low = tx_eq->min_eqd; + + coalesce->use_adaptive_rx_coalesce = rx_eq->enable_aic; + coalesce->use_adaptive_tx_coalesce = tx_eq->enable_aic; + + return 0; +} + +/* + * This routine is used to set interrup coalescing delay *as well as* + * the number of pkts to coalesce for LRO. + */ +static int +be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + u32 tx_max, tx_min, tx_cur; + u32 rx_max, rx_min, rx_cur; + int status = 0; + + if (coalesce->use_adaptive_tx_coalesce == 1) + return -EINVAL; + + adapter->max_rx_coal = coalesce->rx_max_coalesced_frames; + if (adapter->max_rx_coal > MAX_SKB_FRAGS) + adapter->max_rx_coal = MAX_SKB_FRAGS - 1; + + /* if AIC is being turned on now, start with an EQD of 0 */ + if (rx_eq->enable_aic == 0 && + coalesce->use_adaptive_rx_coalesce == 1) { + rx_eq->cur_eqd = 0; + } + rx_eq->enable_aic = coalesce->use_adaptive_rx_coalesce; + + rx_max = coalesce->rx_coalesce_usecs_high; + rx_min = coalesce->rx_coalesce_usecs_low; + rx_cur = coalesce->rx_coalesce_usecs; + + tx_max = coalesce->tx_coalesce_usecs_high; + tx_min = coalesce->tx_coalesce_usecs_low; + tx_cur = coalesce->tx_coalesce_usecs; + + if (tx_cur > BE_MAX_EQD) + tx_cur = BE_MAX_EQD; + if (tx_eq->cur_eqd != tx_cur) { + status = be_cmd_modify_eqd(ctrl, tx_eq->q.id, tx_cur); + if (!status) + tx_eq->cur_eqd = tx_cur; + } + + if (rx_eq->enable_aic) { + if (rx_max > BE_MAX_EQD) + rx_max = BE_MAX_EQD; + if (rx_min > rx_max) + rx_min = rx_max; + rx_eq->max_eqd = rx_max; + rx_eq->min_eqd = rx_min; + if (rx_eq->cur_eqd > rx_max) + rx_eq->cur_eqd = rx_max; + if (rx_eq->cur_eqd < rx_min) + rx_eq->cur_eqd = rx_min; + } else { + if (rx_cur > BE_MAX_EQD) + rx_cur = BE_MAX_EQD; + if (rx_eq->cur_eqd != rx_cur) { + status = be_cmd_modify_eqd(ctrl, rx_eq->q.id, rx_cur); + if (!status) + rx_eq->cur_eqd = rx_cur; + } + } + return 0; +} + +static u32 be_get_rx_csum(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + return adapter->rx_csum; +} + +static int be_set_rx_csum(struct net_device *netdev, uint32_t data) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + if (data) + adapter->rx_csum = true; + else + adapter->rx_csum = false; + + return 0; +} + +static void +be_get_ethtool_stats(struct net_device *netdev, + struct ethtool_stats *stats, uint64_t *data) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_drvr_stats *drvr_stats = &adapter->stats.drvr_stats; + struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va); + struct be_rxf_stats *rxf_stats = &hw_stats->rxf; + struct be_port_rxf_stats *port_stats = + &rxf_stats->port[adapter->port_num]; + struct net_device_stats *net_stats = &adapter->stats.net_stats; + struct be_erx_stats *erx_stats = &hw_stats->erx; + void *p = NULL; + int i; + + for (i = 0; i < ETHTOOL_STATS_NUM; i++) { + switch (et_stats[i].type) { + case NETSTAT: + p = net_stats; + break; + case DRVSTAT: + p = drvr_stats; + break; + case PORTSTAT: + p = port_stats; + break; + case MISCSTAT: + p = rxf_stats; + break; + case ERXSTAT: /* Currently only one ERX stat is provided */ + p = (u32 *)erx_stats + adapter->rx_obj.q.id; + break; + } + + p = (u8 *)p + et_stats[i].offset; + data[i] = (et_stats[i].size == sizeof(u64)) ? + *(u64 *)p: *(u32 *)p; + } + + return; +} + +static void +be_get_stat_strings(struct net_device *netdev, uint32_t stringset, + uint8_t *data) +{ + int i; + switch (stringset) { + case ETH_SS_STATS: + for (i = 0; i < ETHTOOL_STATS_NUM; i++) { + memcpy(data, et_stats[i].desc, ETH_GSTRING_LEN); + data += ETH_GSTRING_LEN; + } + break; + } +} + +static int be_get_stats_count(struct net_device *netdev) +{ + return ETHTOOL_STATS_NUM; +} + +static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) +{ + ecmd->speed = SPEED_10000; + ecmd->duplex = DUPLEX_FULL; + ecmd->autoneg = AUTONEG_DISABLE; + return 0; +} + +static void +be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + ring->rx_max_pending = adapter->rx_obj.q.len; + ring->tx_max_pending = adapter->tx_obj.q.len; + + ring->rx_pending = atomic_read(&adapter->rx_obj.q.used); + ring->tx_pending = atomic_read(&adapter->tx_obj.q.used); +} + +static void +be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + be_cmd_get_flow_control(&adapter->ctrl, &ecmd->tx_pause, + &ecmd->rx_pause); + ecmd->autoneg = AUTONEG_ENABLE; +} + +static int +be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) +{ + struct be_adapter *adapter = netdev_priv(netdev); + int status; + + if (ecmd->autoneg != AUTONEG_ENABLE) + return -EINVAL; + + status = be_cmd_set_flow_control(&adapter->ctrl, ecmd->tx_pause, + ecmd->rx_pause); + if (!status) + dev_warn(&adapter->pdev->dev, "Pause param set failed.\n"); + + return status; +} + +struct ethtool_ops be_ethtool_ops = { + .get_settings = be_get_settings, + .get_drvinfo = be_get_drvinfo, + .get_link = ethtool_op_get_link, + .get_coalesce = be_get_coalesce, + .set_coalesce = be_set_coalesce, + .get_ringparam = be_get_ringparam, + .get_pauseparam = be_get_pauseparam, + .set_pauseparam = be_set_pauseparam, + .get_rx_csum = be_get_rx_csum, + .set_rx_csum = be_set_rx_csum, + .get_tx_csum = ethtool_op_get_tx_csum, + .set_tx_csum = ethtool_op_set_tx_csum, + .get_sg = ethtool_op_get_sg, + .set_sg = ethtool_op_set_sg, + .get_tso = ethtool_op_get_tso, + .set_tso = ethtool_op_set_tso, + .get_strings = be_get_stat_strings, + .get_stats_count = be_get_stats_count, + .get_ethtool_stats = be_get_ethtool_stats, +}; diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h new file mode 100644 index 000000000000..b132aa4893ca --- /dev/null +++ b/drivers/net/benet/be_hw.h @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * All rights reserved. + * + * 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. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +/********* Mailbox door bell *************/ +/* Used for driver communication with the FW. + * The software must write this register twice to post any command. First, + * it writes the register with hi=1 and the upper bits of the physical address + * for the MAILBOX structure. Software must poll the ready bit until this + * is acknowledged. Then, sotware writes the register with hi=0 with the lower + * bits in the address. It must poll the ready bit until the command is + * complete. Upon completion, the MAILBOX will contain a valid completion + * queue entry. + */ +#define MPU_MAILBOX_DB_OFFSET 0x160 +#define MPU_MAILBOX_DB_RDY_MASK 0x1 /* bit 0 */ +#define MPU_MAILBOX_DB_HI_MASK 0x2 /* bit 1 */ + +#define MPU_EP_CONTROL 0 + +/********** MPU semphore ******************/ +#define MPU_EP_SEMAPHORE_OFFSET 0xac +#define EP_SEMAPHORE_POST_STAGE_MASK 0x0000FFFF +#define EP_SEMAPHORE_POST_ERR_MASK 0x1 +#define EP_SEMAPHORE_POST_ERR_SHIFT 31 +/* MPU semphore POST stage values */ +#define POST_STAGE_AWAITING_HOST_RDY 0x1 /* FW awaiting goahead from host */ +#define POST_STAGE_HOST_RDY 0x2 /* Host has given go-ahed to FW */ +#define POST_STAGE_BE_RESET 0x3 /* Host wants to reset chip */ +#define POST_STAGE_ARMFW_RDY 0xc000 /* FW is done with POST */ + +/********* Memory BAR register ************/ +#define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 0xfc +/* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt + * Disable" may still globally block interrupts in addition to individual + * interrupt masks; a mechanism for the device driver to block all interrupts + * atomically without having to arbitrate for the PCI Interrupt Disable bit + * with the OS. + */ +#define MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK (1 << 29) /* bit 29 */ +/* PCI physical function number */ +#define MEMBAR_CTRL_INT_CTRL_PFUNC_MASK 0x7 /* bits 26 - 28 */ +#define MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT 26 + +/********* Event Q door bell *************/ +#define DB_EQ_OFFSET DB_CQ_OFFSET +#define DB_EQ_RING_ID_MASK 0x1FF /* bits 0 - 8 */ +/* Clear the interrupt for this eq */ +#define DB_EQ_CLR_SHIFT (9) /* bit 9 */ +/* Must be 1 */ +#define DB_EQ_EVNT_SHIFT (10) /* bit 10 */ +/* Number of event entries processed */ +#define DB_EQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ +/* Rearm bit */ +#define DB_EQ_REARM_SHIFT (29) /* bit 29 */ + +/********* Compl Q door bell *************/ +#define DB_CQ_OFFSET 0x120 +#define DB_CQ_RING_ID_MASK 0x3FF /* bits 0 - 9 */ +/* Number of event entries processed */ +#define DB_CQ_NUM_POPPED_SHIFT (16) /* bits 16 - 28 */ +/* Rearm bit */ +#define DB_CQ_REARM_SHIFT (29) /* bit 29 */ + +/********** TX ULP door bell *************/ +#define DB_TXULP1_OFFSET 0x60 +#define DB_TXULP_RING_ID_MASK 0x7FF /* bits 0 - 10 */ +/* Number of tx entries posted */ +#define DB_TXULP_NUM_POSTED_SHIFT (16) /* bits 16 - 29 */ +#define DB_TXULP_NUM_POSTED_MASK 0x3FFF /* bits 16 - 29 */ + +/********** RQ(erx) door bell ************/ +#define DB_RQ_OFFSET 0x100 +#define DB_RQ_RING_ID_MASK 0x3FF /* bits 0 - 9 */ +/* Number of rx frags posted */ +#define DB_RQ_NUM_POSTED_SHIFT (24) /* bits 24 - 31 */ + +/* + * BE descriptors: host memory data structures whose formats + * are hardwired in BE silicon. + */ +/* Event Queue Descriptor */ +#define EQ_ENTRY_VALID_MASK 0x1 /* bit 0 */ +#define EQ_ENTRY_RES_ID_MASK 0xFFFF /* bits 16 - 31 */ +#define EQ_ENTRY_RES_ID_SHIFT 16 +struct be_eq_entry { + u32 evt; +}; + +/* TX Queue Descriptor */ +#define ETH_WRB_FRAG_LEN_MASK 0xFFFF +struct be_eth_wrb { + u32 frag_pa_hi; /* dword 0 */ + u32 frag_pa_lo; /* dword 1 */ + u32 rsvd0; /* dword 2 */ + u32 frag_len; /* dword 3: bits 0 - 15 */ +} __packed; + +/* Pseudo amap definition for eth_hdr_wrb in which each bit of the + * actual structure is defined as a byte : used to calculate + * offset/shift/mask of each field */ +struct amap_eth_hdr_wrb { + u8 rsvd0[32]; /* dword 0 */ + u8 rsvd1[32]; /* dword 1 */ + u8 complete; /* dword 2 */ + u8 event; + u8 crc; + u8 forward; + u8 ipsec; + u8 mgmt; + u8 ipcs; + u8 udpcs; + u8 tcpcs; + u8 lso; + u8 vlan; + u8 gso[2]; + u8 num_wrb[5]; + u8 lso_mss[14]; + u8 len[16]; /* dword 3 */ + u8 vlan_tag[16]; +} __packed; + +struct be_eth_hdr_wrb { + u32 dw[4]; +}; + +/* TX Compl Queue Descriptor */ + +/* Pseudo amap definition for eth_tx_compl in which each bit of the + * actual structure is defined as a byte: used to calculate + * offset/shift/mask of each field */ +struct amap_eth_tx_compl { + u8 wrb_index[16]; /* dword 0 */ + u8 ct[2]; /* dword 0 */ + u8 port[2]; /* dword 0 */ + u8 rsvd0[8]; /* dword 0 */ + u8 status[4]; /* dword 0 */ + u8 user_bytes[16]; /* dword 1 */ + u8 nwh_bytes[8]; /* dword 1 */ + u8 lso; /* dword 1 */ + u8 cast_enc[2]; /* dword 1 */ + u8 rsvd1[5]; /* dword 1 */ + u8 rsvd2[32]; /* dword 2 */ + u8 pkts[16]; /* dword 3 */ + u8 ringid[11]; /* dword 3 */ + u8 hash_val[4]; /* dword 3 */ + u8 valid; /* dword 3 */ +} __packed; + +struct be_eth_tx_compl { + u32 dw[4]; +}; + +/* RX Queue Descriptor */ +struct be_eth_rx_d { + u32 fragpa_hi; + u32 fragpa_lo; +}; + +/* RX Compl Queue Descriptor */ + +/* Pseudo amap definition for eth_rx_compl in which each bit of the + * actual structure is defined as a byte: used to calculate + * offset/shift/mask of each field */ +struct amap_eth_rx_compl { + u8 vlan_tag[16]; /* dword 0 */ + u8 pktsize[14]; /* dword 0 */ + u8 port; /* dword 0 */ + u8 ip_opt; /* dword 0 */ + u8 err; /* dword 1 */ + u8 rsshp; /* dword 1 */ + u8 ipf; /* dword 1 */ + u8 tcpf; /* dword 1 */ + u8 udpf; /* dword 1 */ + u8 ipcksm; /* dword 1 */ + u8 l4_cksm; /* dword 1 */ + u8 ip_version; /* dword 1 */ + u8 macdst[6]; /* dword 1 */ + u8 vtp; /* dword 1 */ + u8 rsvd0; /* dword 1 */ + u8 fragndx[10]; /* dword 1 */ + u8 ct[2]; /* dword 1 */ + u8 sw; /* dword 1 */ + u8 numfrags[3]; /* dword 1 */ + u8 rss_flush; /* dword 2 */ + u8 cast_enc[2]; /* dword 2 */ + u8 qnq; /* dword 2 */ + u8 rss_bank; /* dword 2 */ + u8 rsvd1[23]; /* dword 2 */ + u8 lro_pkt; /* dword 2 */ + u8 rsvd2[2]; /* dword 2 */ + u8 valid; /* dword 2 */ + u8 rsshash[32]; /* dword 3 */ +} __packed; + +struct be_eth_rx_compl { + u32 dw[4]; +}; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c new file mode 100644 index 000000000000..897a63de5bdb --- /dev/null +++ b/drivers/net/benet/be_main.c @@ -0,0 +1,1903 @@ +/* + * Copyright (C) 2005 - 2009 ServerEngines + * All rights reserved. + * + * 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. The full GNU General + * Public License is included in this distribution in the file called COPYING. + * + * Contact Information: + * linux-drivers@serverengines.com + * + * ServerEngines + * 209 N. Fair Oaks Ave + * Sunnyvale, CA 94085 + */ + +#include "be.h" + +MODULE_VERSION(DRV_VER); +MODULE_DEVICE_TABLE(pci, be_dev_ids); +MODULE_DESCRIPTION(DRV_DESC " " DRV_VER); +MODULE_AUTHOR("ServerEngines Corporation"); +MODULE_LICENSE("GPL"); + +static unsigned int rx_frag_size = 2048; +module_param(rx_frag_size, uint, S_IRUGO); +MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data."); + +#define BE_VENDOR_ID 0x19a2 +#define BE2_DEVICE_ID_1 0x0211 +static DEFINE_PCI_DEVICE_TABLE(be_dev_ids) = { + { PCI_DEVICE(BE_VENDOR_ID, BE2_DEVICE_ID_1) }, + { 0 } +}; +MODULE_DEVICE_TABLE(pci, be_dev_ids); + +static void be_queue_free(struct be_adapter *adapter, struct be_queue_info *q) +{ + struct be_dma_mem *mem = &q->dma_mem; + if (mem->va) + pci_free_consistent(adapter->pdev, mem->size, + mem->va, mem->dma); +} + +static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q, + u16 len, u16 entry_size) +{ + struct be_dma_mem *mem = &q->dma_mem; + + memset(q, 0, sizeof(*q)); + q->len = len; + q->entry_size = entry_size; + mem->size = len * entry_size; + mem->va = pci_alloc_consistent(adapter->pdev, mem->size, &mem->dma); + if (!mem->va) + return -1; + memset(mem->va, 0, mem->size); + return 0; +} + +static inline void *queue_head_node(struct be_queue_info *q) +{ + return q->dma_mem.va + q->head * q->entry_size; +} + +static inline void *queue_tail_node(struct be_queue_info *q) +{ + return q->dma_mem.va + q->tail * q->entry_size; +} + +static inline void queue_head_inc(struct be_queue_info *q) +{ + index_inc(&q->head, q->len); +} + +static inline void queue_tail_inc(struct be_queue_info *q) +{ + index_inc(&q->tail, q->len); +} + +static void be_intr_set(struct be_ctrl_info *ctrl, bool enable) +{ + u8 __iomem *addr = ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET; + u32 reg = ioread32(addr); + u32 enabled = reg & MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; + if (!enabled && enable) { + reg |= MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; + } else if (enabled && !enable) { + reg &= ~MEMBAR_CTRL_INT_CTRL_HOSTINTR_MASK; + } else { + printk(KERN_WARNING DRV_NAME + ": bad value in membar_int_ctrl reg=0x%x\n", reg); + return; + } + iowrite32(reg, addr); +} + +static void be_rxq_notify(struct be_ctrl_info *ctrl, u16 qid, u16 posted) +{ + u32 val = 0; + val |= qid & DB_RQ_RING_ID_MASK; + val |= posted << DB_RQ_NUM_POSTED_SHIFT; + iowrite32(val, ctrl->db + DB_RQ_OFFSET); +} + +static void be_txq_notify(struct be_ctrl_info *ctrl, u16 qid, u16 posted) +{ + u32 val = 0; + val |= qid & DB_TXULP_RING_ID_MASK; + val |= (posted & DB_TXULP_NUM_POSTED_MASK) << DB_TXULP_NUM_POSTED_SHIFT; + iowrite32(val, ctrl->db + DB_TXULP1_OFFSET); +} + +static void be_eq_notify(struct be_ctrl_info *ctrl, u16 qid, + bool arm, bool clear_int, u16 num_popped) +{ + u32 val = 0; + val |= qid & DB_EQ_RING_ID_MASK; + if (arm) + val |= 1 << DB_EQ_REARM_SHIFT; + if (clear_int) + val |= 1 << DB_EQ_CLR_SHIFT; + val |= 1 << DB_EQ_EVNT_SHIFT; + val |= num_popped << DB_EQ_NUM_POPPED_SHIFT; + iowrite32(val, ctrl->db + DB_EQ_OFFSET); +} + +static void be_cq_notify(struct be_ctrl_info *ctrl, u16 qid, + bool arm, u16 num_popped) +{ + u32 val = 0; + val |= qid & DB_CQ_RING_ID_MASK; + if (arm) + val |= 1 << DB_CQ_REARM_SHIFT; + val |= num_popped << DB_CQ_NUM_POPPED_SHIFT; + iowrite32(val, ctrl->db + DB_CQ_OFFSET); +} + + +static int be_mac_addr_set(struct net_device *netdev, void *p) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct sockaddr *addr = p; + int status = 0; + + if (netif_running(netdev)) { + status = be_cmd_pmac_del(&adapter->ctrl, adapter->if_handle, + adapter->pmac_id); + if (status) + return status; + + status = be_cmd_pmac_add(&adapter->ctrl, (u8 *)addr->sa_data, + adapter->if_handle, &adapter->pmac_id); + } + + if (!status) + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + + return status; +} + +static void netdev_stats_update(struct be_adapter *adapter) +{ + struct be_hw_stats *hw_stats = hw_stats_from_cmd(adapter->stats.cmd.va); + struct be_rxf_stats *rxf_stats = &hw_stats->rxf; + struct be_port_rxf_stats *port_stats = + &rxf_stats->port[adapter->port_num]; + struct net_device_stats *dev_stats = &adapter->stats.net_stats; + + dev_stats->rx_packets = port_stats->rx_total_frames; + dev_stats->tx_packets = port_stats->tx_unicastframes + + port_stats->tx_multicastframes + port_stats->tx_broadcastframes; + dev_stats->rx_bytes = (u64) port_stats->rx_bytes_msd << 32 | + (u64) port_stats->rx_bytes_lsd; + dev_stats->tx_bytes = (u64) port_stats->tx_bytes_msd << 32 | + (u64) port_stats->tx_bytes_lsd; + + /* bad pkts received */ + dev_stats->rx_errors = port_stats->rx_crc_errors + + port_stats->rx_alignment_symbol_errors + + port_stats->rx_in_range_errors + + port_stats->rx_out_range_errors + port_stats->rx_frame_too_long; + + /* packet transmit problems */ + dev_stats->tx_errors = 0; + + /* no space in linux buffers */ + dev_stats->rx_dropped = 0; + + /* no space available in linux */ + dev_stats->tx_dropped = 0; + + dev_stats->multicast = port_stats->tx_multicastframes; + dev_stats->collisions = 0; + + /* detailed rx errors */ + dev_stats->rx_length_errors = port_stats->rx_in_range_errors + + port_stats->rx_out_range_errors + port_stats->rx_frame_too_long; + /* receive ring buffer overflow */ + dev_stats->rx_over_errors = 0; + dev_stats->rx_crc_errors = port_stats->rx_crc_errors; + + /* frame alignment errors */ + dev_stats->rx_frame_errors = port_stats->rx_alignment_symbol_errors; + /* receiver fifo overrun */ + /* drops_no_pbuf is no per i/f, it's per BE card */ + dev_stats->rx_fifo_errors = port_stats->rx_fifo_overflow + + port_stats->rx_input_fifo_overflow + + rxf_stats->rx_drops_no_pbuf; + /* receiver missed packetd */ + dev_stats->rx_missed_errors = 0; + /* detailed tx_errors */ + dev_stats->tx_aborted_errors = 0; + dev_stats->tx_carrier_errors = 0; + dev_stats->tx_fifo_errors = 0; + dev_stats->tx_heartbeat_errors = 0; + dev_stats->tx_window_errors = 0; +} + +static void be_link_status_update(struct be_adapter *adapter) +{ + struct be_link_info *prev = &adapter->link; + struct be_link_info now = { 0 }; + struct net_device *netdev = adapter->netdev; + + be_cmd_link_status_query(&adapter->ctrl, &now); + + /* If link came up or went down */ + if (now.speed != prev->speed && (now.speed == PHY_LINK_SPEED_ZERO || + prev->speed == PHY_LINK_SPEED_ZERO)) { + if (now.speed == PHY_LINK_SPEED_ZERO) { + netif_stop_queue(netdev); + netif_carrier_off(netdev); + printk(KERN_INFO "%s: Link down\n", netdev->name); + } else { + netif_start_queue(netdev); + netif_carrier_on(netdev); + printk(KERN_INFO "%s: Link up\n", netdev->name); + } + } + *prev = now; +} + +/* Update the EQ delay n BE based on the RX frags consumed / sec */ +static void be_rx_eqd_update(struct be_adapter *adapter) +{ + u32 eqd; + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_drvr_stats *stats = &adapter->stats.drvr_stats; + + /* Update once a second */ + if (((jiffies - stats->rx_fps_jiffies) < HZ) || rx_eq->enable_aic == 0) + return; + + stats->be_rx_fps = (stats->be_rx_frags - stats->be_prev_rx_frags) / + ((jiffies - stats->rx_fps_jiffies) / HZ); + + stats->rx_fps_jiffies = jiffies; + stats->be_prev_rx_frags = stats->be_rx_frags; + eqd = stats->be_rx_fps / 110000; + eqd = eqd << 3; + if (eqd > rx_eq->max_eqd) + eqd = rx_eq->max_eqd; + if (eqd < rx_eq->min_eqd) + eqd = rx_eq->min_eqd; + if (eqd < 10) + eqd = 0; + if (eqd != rx_eq->cur_eqd) + be_cmd_modify_eqd(ctrl, rx_eq->q.id, eqd); + + rx_eq->cur_eqd = eqd; +} + +static void be_worker(struct work_struct *work) +{ + struct be_adapter *adapter = + container_of(work, struct be_adapter, work.work); + int status; + + /* Check link */ + be_link_status_update(adapter); + + /* Get Stats */ + status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); + if (!status) + netdev_stats_update(adapter); + + /* Set EQ delay */ + be_rx_eqd_update(adapter); + + schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); +} + +static struct net_device_stats *be_get_stats(struct net_device *dev) +{ + struct be_adapter *adapter = netdev_priv(dev); + + return &adapter->stats.net_stats; +} + +static void be_tx_stats_update(struct be_adapter *adapter, + u32 wrb_cnt, u32 copied, bool stopped) +{ + struct be_drvr_stats *stats = &adapter->stats.drvr_stats; + stats->be_tx_reqs++; + stats->be_tx_wrbs += wrb_cnt; + stats->be_tx_bytes += copied; + if (stopped) + stats->be_tx_stops++; + + /* Update tx rate once in two seconds */ + if ((jiffies - stats->be_tx_jiffies) > 2 * HZ) { + u32 r; + r = (stats->be_tx_bytes - stats->be_tx_bytes_prev) / + ((u32) (jiffies - stats->be_tx_jiffies) / HZ); + r = (r / 1000000); /* M bytes/s */ + stats->be_tx_rate = (r * 8); /* M bits/s */ + stats->be_tx_jiffies = jiffies; + stats->be_tx_bytes_prev = stats->be_tx_bytes; + } +} + +/* Determine number of WRB entries needed to xmit data in an skb */ +static u32 wrb_cnt_for_skb(struct sk_buff *skb, bool *dummy) +{ + int cnt = 0; + while (skb) { + if (skb->len > skb->data_len) + cnt++; + cnt += skb_shinfo(skb)->nr_frags; + skb = skb_shinfo(skb)->frag_list; + } + /* to account for hdr wrb */ + cnt++; + if (cnt & 1) { + /* add a dummy to make it an even num */ + cnt++; + *dummy = true; + } else + *dummy = false; + BUG_ON(cnt > BE_MAX_TX_FRAG_COUNT); + return cnt; +} + +static inline void wrb_fill(struct be_eth_wrb *wrb, u64 addr, int len) +{ + wrb->frag_pa_hi = upper_32_bits(addr); + wrb->frag_pa_lo = addr & 0xFFFFFFFF; + wrb->frag_len = len & ETH_WRB_FRAG_LEN_MASK; +} + +static void wrb_fill_hdr(struct be_eth_hdr_wrb *hdr, struct sk_buff *skb, + bool vlan, u32 wrb_cnt, u32 len) +{ + memset(hdr, 0, sizeof(*hdr)); + + AMAP_SET_BITS(struct amap_eth_hdr_wrb, crc, hdr, 1); + + if (skb_shinfo(skb)->gso_segs > 1 && skb_shinfo(skb)->gso_size) { + AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso, hdr, 1); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, lso_mss, + hdr, skb_shinfo(skb)->gso_size); + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { + if (is_tcp_pkt(skb)) + AMAP_SET_BITS(struct amap_eth_hdr_wrb, tcpcs, hdr, 1); + else if (is_udp_pkt(skb)) + AMAP_SET_BITS(struct amap_eth_hdr_wrb, udpcs, hdr, 1); + } + + if (vlan && vlan_tx_tag_present(skb)) { + AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan, hdr, 1); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, vlan_tag, + hdr, vlan_tx_tag_get(skb)); + } + + AMAP_SET_BITS(struct amap_eth_hdr_wrb, event, hdr, 1); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, complete, hdr, 1); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, num_wrb, hdr, wrb_cnt); + AMAP_SET_BITS(struct amap_eth_hdr_wrb, len, hdr, len); +} + + +static int make_tx_wrbs(struct be_adapter *adapter, + struct sk_buff *skb, u32 wrb_cnt, bool dummy_wrb) +{ + u64 busaddr; + u32 i, copied = 0; + struct pci_dev *pdev = adapter->pdev; + struct sk_buff *first_skb = skb; + struct be_queue_info *txq = &adapter->tx_obj.q; + struct be_eth_wrb *wrb; + struct be_eth_hdr_wrb *hdr; + + atomic_add(wrb_cnt, &txq->used); + hdr = queue_head_node(txq); + queue_head_inc(txq); + + while (skb) { + if (skb->len > skb->data_len) { + int len = skb->len - skb->data_len; + busaddr = pci_map_single(pdev, skb->data, len, + PCI_DMA_TODEVICE); + wrb = queue_head_node(txq); + wrb_fill(wrb, busaddr, len); + be_dws_cpu_to_le(wrb, sizeof(*wrb)); + queue_head_inc(txq); + copied += len; + } + + for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { + struct skb_frag_struct *frag = + &skb_shinfo(skb)->frags[i]; + busaddr = pci_map_page(pdev, frag->page, + frag->page_offset, + frag->size, PCI_DMA_TODEVICE); + wrb = queue_head_node(txq); + wrb_fill(wrb, busaddr, frag->size); + be_dws_cpu_to_le(wrb, sizeof(*wrb)); + queue_head_inc(txq); + copied += frag->size; + } + skb = skb_shinfo(skb)->frag_list; + } + + if (dummy_wrb) { + wrb = queue_head_node(txq); + wrb_fill(wrb, 0, 0); + be_dws_cpu_to_le(wrb, sizeof(*wrb)); + queue_head_inc(txq); + } + + wrb_fill_hdr(hdr, first_skb, adapter->vlan_grp ? true : false, + wrb_cnt, copied); + be_dws_cpu_to_le(hdr, sizeof(*hdr)); + + return copied; +} + +static int be_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_tx_obj *tx_obj = &adapter->tx_obj; + struct be_queue_info *txq = &tx_obj->q; + u32 wrb_cnt = 0, copied = 0; + u32 start = txq->head; + bool dummy_wrb, stopped = false; + + wrb_cnt = wrb_cnt_for_skb(skb, &dummy_wrb); + + copied = make_tx_wrbs(adapter, skb, wrb_cnt, dummy_wrb); + + /* record the sent skb in the sent_skb table */ + BUG_ON(tx_obj->sent_skb_list[start]); + tx_obj->sent_skb_list[start] = skb; + + /* Ensure that txq has space for the next skb; Else stop the queue + * *BEFORE* ringing the tx doorbell, so that we serialze the + * tx compls of the current transmit which'll wake up the queue + */ + if ((BE_MAX_TX_FRAG_COUNT + atomic_read(&txq->used)) >= txq->len) { + netif_stop_queue(netdev); + stopped = true; + } + + be_txq_notify(&adapter->ctrl, txq->id, wrb_cnt); + + netdev->trans_start = jiffies; + + be_tx_stats_update(adapter, wrb_cnt, copied, stopped); + return NETDEV_TX_OK; +} + +static int be_change_mtu(struct net_device *netdev, int new_mtu) +{ + struct be_adapter *adapter = netdev_priv(netdev); + if (new_mtu < BE_MIN_MTU || + new_mtu > BE_MAX_JUMBO_FRAME_SIZE) { + dev_info(&adapter->pdev->dev, + "MTU must be between %d and %d bytes\n", + BE_MIN_MTU, BE_MAX_JUMBO_FRAME_SIZE); + return -EINVAL; + } + dev_info(&adapter->pdev->dev, "MTU changed from %d to %d bytes\n", + netdev->mtu, new_mtu); + netdev->mtu = new_mtu; + return 0; +} + +/* + * if there are BE_NUM_VLANS_SUPPORTED or lesser number of VLANS configured, + * program them in BE. If more than BE_NUM_VLANS_SUPPORTED are configured, + * set the BE in promiscuous VLAN mode. + */ +static void be_vids_config(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + u16 vtag[BE_NUM_VLANS_SUPPORTED]; + u16 ntags = 0, i; + + if (adapter->num_vlans <= BE_NUM_VLANS_SUPPORTED) { + /* Construct VLAN Table to give to HW */ + for (i = 0; i < VLAN_GROUP_ARRAY_LEN; i++) { + if (adapter->vlan_tag[i]) { + vtag[ntags] = cpu_to_le16(i); + ntags++; + } + } + be_cmd_vlan_config(&adapter->ctrl, adapter->if_handle, + vtag, ntags, 1, 0); + } else { + be_cmd_vlan_config(&adapter->ctrl, adapter->if_handle, + NULL, 0, 1, 1); + } +} + +static void be_vlan_register(struct net_device *netdev, struct vlan_group *grp) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + struct be_ctrl_info *ctrl = &adapter->ctrl; + + be_eq_notify(ctrl, rx_eq->q.id, false, false, 0); + be_eq_notify(ctrl, tx_eq->q.id, false, false, 0); + adapter->vlan_grp = grp; + be_eq_notify(ctrl, rx_eq->q.id, true, false, 0); + be_eq_notify(ctrl, tx_eq->q.id, true, false, 0); +} + +static void be_vlan_add_vid(struct net_device *netdev, u16 vid) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + adapter->num_vlans++; + adapter->vlan_tag[vid] = 1; + + be_vids_config(netdev); +} + +static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + adapter->num_vlans--; + adapter->vlan_tag[vid] = 0; + + vlan_group_set_device(adapter->vlan_grp, vid, NULL); + be_vids_config(netdev); +} + +static void be_set_multicast_filter(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct dev_mc_list *mc_ptr; + u8 mac_addr[32][ETH_ALEN]; + int i = 0; + + if (netdev->flags & IFF_ALLMULTI) { + /* set BE in Multicast promiscuous */ + be_cmd_mcast_mac_set(&adapter->ctrl, + adapter->if_handle, NULL, 0, true); + return; + } + + for (mc_ptr = netdev->mc_list; mc_ptr; mc_ptr = mc_ptr->next) { + memcpy(&mac_addr[i][0], mc_ptr->dmi_addr, ETH_ALEN); + if (++i >= 32) { + be_cmd_mcast_mac_set(&adapter->ctrl, + adapter->if_handle, &mac_addr[0][0], i, false); + i = 0; + } + + } + + if (i) { + /* reset the promiscuous mode also. */ + be_cmd_mcast_mac_set(&adapter->ctrl, + adapter->if_handle, &mac_addr[0][0], i, false); + } +} + +static void be_set_multicast_list(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + if (netdev->flags & IFF_PROMISC) { + be_cmd_promiscuous_config(&adapter->ctrl, adapter->port_num, 1); + } else { + be_cmd_promiscuous_config(&adapter->ctrl, adapter->port_num, 0); + be_set_multicast_filter(netdev); + } +} + +static void be_rx_rate_update(struct be_adapter *adapter, u32 pktsize, + u16 numfrags) +{ + struct be_drvr_stats *stats = &adapter->stats.drvr_stats; + u32 rate; + + stats->be_rx_compl++; + stats->be_rx_frags += numfrags; + stats->be_rx_bytes += pktsize; + + /* Update the rate once in two seconds */ + if ((jiffies - stats->be_rx_jiffies) < 2 * HZ) + return; + + rate = (stats->be_rx_bytes - stats->be_rx_bytes_prev) / + ((u32) (jiffies - stats->be_rx_jiffies) / HZ); + rate = (rate / 1000000); /* MB/Sec */ + stats->be_rx_rate = (rate * 8); /* Mega Bits/Sec */ + stats->be_rx_jiffies = jiffies; + stats->be_rx_bytes_prev = stats->be_rx_bytes; +} + +static struct be_rx_page_info * +get_rx_page_info(struct be_adapter *adapter, u16 frag_idx) +{ + struct be_rx_page_info *rx_page_info; + struct be_queue_info *rxq = &adapter->rx_obj.q; + + rx_page_info = &adapter->rx_obj.page_info_tbl[frag_idx]; + BUG_ON(!rx_page_info->page); + + if (rx_page_info->last_page_user) + pci_unmap_page(adapter->pdev, pci_unmap_addr(rx_page_info, bus), + adapter->big_page_size, PCI_DMA_FROMDEVICE); + + atomic_dec(&rxq->used); + return rx_page_info; +} + +/* Throwaway the data in the Rx completion */ +static void be_rx_compl_discard(struct be_adapter *adapter, + struct be_eth_rx_compl *rxcp) +{ + struct be_queue_info *rxq = &adapter->rx_obj.q; + struct be_rx_page_info *page_info; + u16 rxq_idx, i, num_rcvd; + + rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); + num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); + + for (i = 0; i < num_rcvd; i++) { + page_info = get_rx_page_info(adapter, rxq_idx); + put_page(page_info->page); + memset(page_info, 0, sizeof(*page_info)); + index_inc(&rxq_idx, rxq->len); + } +} + +/* + * skb_fill_rx_data forms a complete skb for an ether frame + * indicated by rxcp. + */ +static void skb_fill_rx_data(struct be_adapter *adapter, + struct sk_buff *skb, struct be_eth_rx_compl *rxcp) +{ + struct be_queue_info *rxq = &adapter->rx_obj.q; + struct be_rx_page_info *page_info; + u16 rxq_idx, i, num_rcvd; + u32 pktsize, hdr_len, curr_frag_len; + u8 *start; + + rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); + pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); + num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); + + page_info = get_rx_page_info(adapter, rxq_idx); + + start = page_address(page_info->page) + page_info->page_offset; + prefetch(start); + + /* Copy data in the first descriptor of this completion */ + curr_frag_len = min(pktsize, rx_frag_size); + + /* Copy the header portion into skb_data */ + hdr_len = min((u32)BE_HDR_LEN, curr_frag_len); + memcpy(skb->data, start, hdr_len); + skb->len = curr_frag_len; + if (curr_frag_len <= BE_HDR_LEN) { /* tiny packet */ + /* Complete packet has now been moved to data */ + put_page(page_info->page); + skb->data_len = 0; + skb->tail += curr_frag_len; + } else { + skb_shinfo(skb)->nr_frags = 1; + skb_shinfo(skb)->frags[0].page = page_info->page; + skb_shinfo(skb)->frags[0].page_offset = + page_info->page_offset + hdr_len; + skb_shinfo(skb)->frags[0].size = curr_frag_len - hdr_len; + skb->data_len = curr_frag_len - hdr_len; + skb->tail += hdr_len; + } + memset(page_info, 0, sizeof(*page_info)); + + if (pktsize <= rx_frag_size) { + BUG_ON(num_rcvd != 1); + return; + } + + /* More frags present for this completion */ + pktsize -= curr_frag_len; /* account for above copied frag */ + for (i = 1; i < num_rcvd; i++) { + index_inc(&rxq_idx, rxq->len); + page_info = get_rx_page_info(adapter, rxq_idx); + + curr_frag_len = min(pktsize, rx_frag_size); + + skb_shinfo(skb)->frags[i].page = page_info->page; + skb_shinfo(skb)->frags[i].page_offset = page_info->page_offset; + skb_shinfo(skb)->frags[i].size = curr_frag_len; + skb->len += curr_frag_len; + skb->data_len += curr_frag_len; + skb_shinfo(skb)->nr_frags++; + pktsize -= curr_frag_len; + + memset(page_info, 0, sizeof(*page_info)); + } + + be_rx_rate_update(adapter, pktsize, num_rcvd); + return; +} + +/* Process the RX completion indicated by rxcp when LRO is disabled */ +static void be_rx_compl_process(struct be_adapter *adapter, + struct be_eth_rx_compl *rxcp) +{ + struct sk_buff *skb; + u32 vtp, vid; + int l4_cksm; + + l4_cksm = AMAP_GET_BITS(struct amap_eth_rx_compl, l4_cksm, rxcp); + vtp = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); + + skb = netdev_alloc_skb(adapter->netdev, BE_HDR_LEN + NET_IP_ALIGN); + if (!skb) { + if (net_ratelimit()) + dev_warn(&adapter->pdev->dev, "skb alloc failed\n"); + be_rx_compl_discard(adapter, rxcp); + return; + } + + skb_reserve(skb, NET_IP_ALIGN); + + skb_fill_rx_data(adapter, skb, rxcp); + + if (l4_cksm && adapter->rx_csum) + skb->ip_summed = CHECKSUM_UNNECESSARY; + else + skb->ip_summed = CHECKSUM_NONE; + + skb->truesize = skb->len + sizeof(struct sk_buff); + skb->protocol = eth_type_trans(skb, adapter->netdev); + skb->dev = adapter->netdev; + + if (vtp) { + if (!adapter->vlan_grp || adapter->num_vlans == 0) { + kfree_skb(skb); + return; + } + vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); + vid = be16_to_cpu(vid); + vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, vid); + } else { + netif_receive_skb(skb); + } + + adapter->netdev->last_rx = jiffies; + + return; +} + +/* Process the RX completion indicated by rxcp when LRO is enabled */ +static void be_rx_compl_process_lro(struct be_adapter *adapter, + struct be_eth_rx_compl *rxcp) +{ + struct be_rx_page_info *page_info; + struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME]; + struct be_queue_info *rxq = &adapter->rx_obj.q; + u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len; + u16 i, rxq_idx = 0, vid; + + num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp); + pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp); + vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp); + rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp); + + remaining = pkt_size; + for (i = 0; i < num_rcvd; i++) { + page_info = get_rx_page_info(adapter, rxq_idx); + + curr_frag_len = min(remaining, rx_frag_size); + + rx_frags[i].page = page_info->page; + rx_frags[i].page_offset = page_info->page_offset; + rx_frags[i].size = curr_frag_len; + remaining -= curr_frag_len; + + index_inc(&rxq_idx, rxq->len); + + memset(page_info, 0, sizeof(*page_info)); + } + + if (likely(!vlanf)) { + lro_receive_frags(&adapter->rx_obj.lro_mgr, rx_frags, pkt_size, + pkt_size, NULL, 0); + } else { + vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp); + vid = be16_to_cpu(vid); + + if (!adapter->vlan_grp || adapter->num_vlans == 0) + return; + + lro_vlan_hwaccel_receive_frags(&adapter->rx_obj.lro_mgr, + rx_frags, pkt_size, pkt_size, adapter->vlan_grp, + vid, NULL, 0); + } + + be_rx_rate_update(adapter, pkt_size, num_rcvd); + return; +} + +static struct be_eth_rx_compl *be_rx_compl_get(struct be_adapter *adapter) +{ + struct be_eth_rx_compl *rxcp = queue_tail_node(&adapter->rx_obj.cq); + + if (rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] == 0) + return NULL; + + be_dws_le_to_cpu(rxcp, sizeof(*rxcp)); + + rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] = 0; + + queue_tail_inc(&adapter->rx_obj.cq); + return rxcp; +} + +static inline struct page *be_alloc_pages(u32 size) +{ + gfp_t alloc_flags = GFP_ATOMIC; + u32 order = get_order(size); + if (order > 0) + alloc_flags |= __GFP_COMP; + return alloc_pages(alloc_flags, order); +} + +/* + * Allocate a page, split it to fragments of size rx_frag_size and post as + * receive buffers to BE + */ +static void be_post_rx_frags(struct be_adapter *adapter) +{ + struct be_rx_page_info *page_info_tbl = adapter->rx_obj.page_info_tbl; + struct be_rx_page_info *page_info = NULL; + struct be_queue_info *rxq = &adapter->rx_obj.q; + struct page *pagep = NULL; + struct be_eth_rx_d *rxd; + u64 page_dmaaddr = 0, frag_dmaaddr; + u32 posted, page_offset = 0; + + + page_info = &page_info_tbl[rxq->head]; + for (posted = 0; posted < MAX_RX_POST && !page_info->page; posted++) { + if (!pagep) { + pagep = be_alloc_pages(adapter->big_page_size); + if (unlikely(!pagep)) { + drvr_stats(adapter)->be_ethrx_post_fail++; + break; + } + page_dmaaddr = pci_map_page(adapter->pdev, pagep, 0, + adapter->big_page_size, + PCI_DMA_FROMDEVICE); + page_info->page_offset = 0; + } else { + get_page(pagep); + page_info->page_offset = page_offset + rx_frag_size; + } + page_offset = page_info->page_offset; + page_info->page = pagep; + pci_unmap_addr_set(page_info, bus, page_dmaaddr); + frag_dmaaddr = page_dmaaddr + page_info->page_offset; + + rxd = queue_head_node(rxq); + rxd->fragpa_lo = cpu_to_le32(frag_dmaaddr & 0xFFFFFFFF); + rxd->fragpa_hi = cpu_to_le32(upper_32_bits(frag_dmaaddr)); + queue_head_inc(rxq); + + /* Any space left in the current big page for another frag? */ + if ((page_offset + rx_frag_size + rx_frag_size) > + adapter->big_page_size) { + pagep = NULL; + page_info->last_page_user = true; + } + page_info = &page_info_tbl[rxq->head]; + } + if (pagep) + page_info->last_page_user = true; + + if (posted) { + be_rxq_notify(&adapter->ctrl, rxq->id, posted); + atomic_add(posted, &rxq->used); + } + + return; +} + +static struct be_eth_tx_compl * +be_tx_compl_get(struct be_adapter *adapter) +{ + struct be_queue_info *tx_cq = &adapter->tx_obj.cq; + struct be_eth_tx_compl *txcp = queue_tail_node(tx_cq); + + if (txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] == 0) + return NULL; + + be_dws_le_to_cpu(txcp, sizeof(*txcp)); + + txcp->dw[offsetof(struct amap_eth_tx_compl, valid) / 32] = 0; + + queue_tail_inc(tx_cq); + return txcp; +} + +static void be_tx_compl_process(struct be_adapter *adapter, u16 last_index) +{ + struct be_queue_info *txq = &adapter->tx_obj.q; + struct be_eth_wrb *wrb; + struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; + struct sk_buff *sent_skb; + u64 busaddr; + u16 cur_index, num_wrbs = 0; + + cur_index = txq->tail; + sent_skb = sent_skbs[cur_index]; + BUG_ON(!sent_skb); + sent_skbs[cur_index] = NULL; + + do { + cur_index = txq->tail; + wrb = queue_tail_node(txq); + be_dws_le_to_cpu(wrb, sizeof(*wrb)); + busaddr = ((u64)wrb->frag_pa_hi << 32) | (u64)wrb->frag_pa_lo; + if (busaddr != 0) { + pci_unmap_single(adapter->pdev, busaddr, + wrb->frag_len, PCI_DMA_TODEVICE); + } + num_wrbs++; + queue_tail_inc(txq); + } while (cur_index != last_index); + + atomic_sub(num_wrbs, &txq->used); + + kfree_skb(sent_skb); +} + +static void be_rx_q_clean(struct be_adapter *adapter) +{ + struct be_rx_page_info *page_info; + struct be_queue_info *rxq = &adapter->rx_obj.q; + struct be_queue_info *rx_cq = &adapter->rx_obj.cq; + struct be_eth_rx_compl *rxcp; + u16 tail; + + /* First cleanup pending rx completions */ + while ((rxcp = be_rx_compl_get(adapter)) != NULL) { + be_rx_compl_discard(adapter, rxcp); + be_cq_notify(&adapter->ctrl, rx_cq->id, true, 1); + } + + /* Then free posted rx buffer that were not used */ + tail = (rxq->head + rxq->len - atomic_read(&rxq->used)) % rxq->len; + for (; tail != rxq->head; index_inc(&tail, rxq->len)) { + page_info = get_rx_page_info(adapter, tail); + put_page(page_info->page); + memset(page_info, 0, sizeof(*page_info)); + } + BUG_ON(atomic_read(&rxq->used)); +} + +static void be_tx_q_clean(struct be_adapter *adapter) +{ + struct sk_buff **sent_skbs = adapter->tx_obj.sent_skb_list; + struct sk_buff *sent_skb; + struct be_queue_info *txq = &adapter->tx_obj.q; + u16 last_index; + bool dummy_wrb; + + while (atomic_read(&txq->used)) { + sent_skb = sent_skbs[txq->tail]; + last_index = txq->tail; + index_adv(&last_index, + wrb_cnt_for_skb(sent_skb, &dummy_wrb) - 1, txq->len); + be_tx_compl_process(adapter, last_index); + } +} + +static void be_tx_queues_destroy(struct be_adapter *adapter) +{ + struct be_queue_info *q; + + q = &adapter->tx_obj.q; + if (q->created) + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_TXQ); + be_queue_free(adapter, q); + + q = &adapter->tx_obj.cq; + if (q->created) + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_CQ); + be_queue_free(adapter, q); + + /* No more tx completions can be rcvd now; clean up if there are + * any pending completions or pending tx requests */ + be_tx_q_clean(adapter); + + q = &adapter->tx_eq.q; + if (q->created) + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_EQ); + be_queue_free(adapter, q); +} + +static int be_tx_queues_create(struct be_adapter *adapter) +{ + struct be_queue_info *eq, *q, *cq; + + adapter->tx_eq.max_eqd = 0; + adapter->tx_eq.min_eqd = 0; + adapter->tx_eq.cur_eqd = 96; + adapter->tx_eq.enable_aic = false; + /* Alloc Tx Event queue */ + eq = &adapter->tx_eq.q; + if (be_queue_alloc(adapter, eq, EVNT_Q_LEN, sizeof(struct be_eq_entry))) + return -1; + + /* Ask BE to create Tx Event queue */ + if (be_cmd_eq_create(&adapter->ctrl, eq, adapter->tx_eq.cur_eqd)) + goto tx_eq_free; + /* Alloc TX eth compl queue */ + cq = &adapter->tx_obj.cq; + if (be_queue_alloc(adapter, cq, TX_CQ_LEN, + sizeof(struct be_eth_tx_compl))) + goto tx_eq_destroy; + + /* Ask BE to create Tx eth compl queue */ + if (be_cmd_cq_create(&adapter->ctrl, cq, eq, false, false, 3)) + goto tx_cq_free; + + /* Alloc TX eth queue */ + q = &adapter->tx_obj.q; + if (be_queue_alloc(adapter, q, TX_Q_LEN, sizeof(struct be_eth_wrb))) + goto tx_cq_destroy; + + /* Ask BE to create Tx eth queue */ + if (be_cmd_txq_create(&adapter->ctrl, q, cq)) + goto tx_q_free; + return 0; + +tx_q_free: + be_queue_free(adapter, q); +tx_cq_destroy: + be_cmd_q_destroy(&adapter->ctrl, cq, QTYPE_CQ); +tx_cq_free: + be_queue_free(adapter, cq); +tx_eq_destroy: + be_cmd_q_destroy(&adapter->ctrl, eq, QTYPE_EQ); +tx_eq_free: + be_queue_free(adapter, eq); + return -1; +} + +static void be_rx_queues_destroy(struct be_adapter *adapter) +{ + struct be_queue_info *q; + + q = &adapter->rx_obj.q; + if (q->created) { + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_RXQ); + be_rx_q_clean(adapter); + } + be_queue_free(adapter, q); + + q = &adapter->rx_obj.cq; + if (q->created) + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_CQ); + be_queue_free(adapter, q); + + q = &adapter->rx_eq.q; + if (q->created) + be_cmd_q_destroy(&adapter->ctrl, q, QTYPE_EQ); + be_queue_free(adapter, q); +} + +static int be_rx_queues_create(struct be_adapter *adapter) +{ + struct be_queue_info *eq, *q, *cq; + int rc; + + adapter->max_rx_coal = BE_MAX_FRAGS_PER_FRAME; + adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE; + adapter->rx_eq.max_eqd = BE_MAX_EQD; + adapter->rx_eq.min_eqd = 0; + adapter->rx_eq.cur_eqd = 0; + adapter->rx_eq.enable_aic = true; + + /* Alloc Rx Event queue */ + eq = &adapter->rx_eq.q; + rc = be_queue_alloc(adapter, eq, EVNT_Q_LEN, + sizeof(struct be_eq_entry)); + if (rc) + return rc; + + /* Ask BE to create Rx Event queue */ + rc = be_cmd_eq_create(&adapter->ctrl, eq, adapter->rx_eq.cur_eqd); + if (rc) + goto rx_eq_free; + + /* Alloc RX eth compl queue */ + cq = &adapter->rx_obj.cq; + rc = be_queue_alloc(adapter, cq, RX_CQ_LEN, + sizeof(struct be_eth_rx_compl)); + if (rc) + goto rx_eq_destroy; + + /* Ask BE to create Rx eth compl queue */ + rc = be_cmd_cq_create(&adapter->ctrl, cq, eq, false, false, 3); + if (rc) + goto rx_cq_free; + + /* Alloc RX eth queue */ + q = &adapter->rx_obj.q; + rc = be_queue_alloc(adapter, q, RX_Q_LEN, sizeof(struct be_eth_rx_d)); + if (rc) + goto rx_cq_destroy; + + /* Ask BE to create Rx eth queue */ + rc = be_cmd_rxq_create(&adapter->ctrl, q, cq->id, rx_frag_size, + BE_MAX_JUMBO_FRAME_SIZE, adapter->if_handle, false); + if (rc) + goto rx_q_free; + + return 0; +rx_q_free: + be_queue_free(adapter, q); +rx_cq_destroy: + be_cmd_q_destroy(&adapter->ctrl, cq, QTYPE_CQ); +rx_cq_free: + be_queue_free(adapter, cq); +rx_eq_destroy: + be_cmd_q_destroy(&adapter->ctrl, eq, QTYPE_EQ); +rx_eq_free: + be_queue_free(adapter, eq); + return rc; +} +static bool event_get(struct be_eq_obj *eq_obj, u16 *rid) +{ + struct be_eq_entry *entry = queue_tail_node(&eq_obj->q); + u32 evt = entry->evt; + + if (!evt) + return false; + + evt = le32_to_cpu(evt); + *rid = (evt >> EQ_ENTRY_RES_ID_SHIFT) & EQ_ENTRY_RES_ID_MASK; + entry->evt = 0; + queue_tail_inc(&eq_obj->q); + return true; +} + +static int event_handle(struct be_ctrl_info *ctrl, + struct be_eq_obj *eq_obj) +{ + u16 rid = 0, num = 0; + + while (event_get(eq_obj, &rid)) + num++; + + /* We can see an interrupt and no event */ + be_eq_notify(ctrl, eq_obj->q.id, true, true, num); + if (num) + napi_schedule(&eq_obj->napi); + + return num; +} + +static irqreturn_t be_intx(int irq, void *dev) +{ + struct be_adapter *adapter = dev; + struct be_ctrl_info *ctrl = &adapter->ctrl; + int rx, tx; + + tx = event_handle(ctrl, &adapter->tx_eq); + rx = event_handle(ctrl, &adapter->rx_eq); + + if (rx || tx) + return IRQ_HANDLED; + else + return IRQ_NONE; +} + +static irqreturn_t be_msix_rx(int irq, void *dev) +{ + struct be_adapter *adapter = dev; + + event_handle(&adapter->ctrl, &adapter->rx_eq); + + return IRQ_HANDLED; +} + +static irqreturn_t be_msix_tx(int irq, void *dev) +{ + struct be_adapter *adapter = dev; + + event_handle(&adapter->ctrl, &adapter->tx_eq); + + return IRQ_HANDLED; +} + +static inline bool do_lro(struct be_adapter *adapter, + struct be_eth_rx_compl *rxcp) +{ + int err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp); + int tcp_frame = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp); + + if (err) + drvr_stats(adapter)->be_rxcp_err++; + + return (!tcp_frame || err || (adapter->max_rx_coal <= 1)) ? + false : true; +} + +int be_poll_rx(struct napi_struct *napi, int budget) +{ + struct be_eq_obj *rx_eq = container_of(napi, struct be_eq_obj, napi); + struct be_adapter *adapter = + container_of(rx_eq, struct be_adapter, rx_eq); + struct be_queue_info *rx_cq = &adapter->rx_obj.cq; + struct be_eth_rx_compl *rxcp; + u32 work_done; + + for (work_done = 0; work_done < budget; work_done++) { + rxcp = be_rx_compl_get(adapter); + if (!rxcp) + break; + + if (do_lro(adapter, rxcp)) + be_rx_compl_process_lro(adapter, rxcp); + else + be_rx_compl_process(adapter, rxcp); + } + + lro_flush_all(&adapter->rx_obj.lro_mgr); + + /* Refill the queue */ + if (atomic_read(&adapter->rx_obj.q.used) < RX_FRAGS_REFILL_WM) + be_post_rx_frags(adapter); + + /* All consumed */ + if (work_done < budget) { + napi_complete(napi); + be_cq_notify(&adapter->ctrl, rx_cq->id, true, work_done); + } else { + /* More to be consumed; continue with interrupts disabled */ + be_cq_notify(&adapter->ctrl, rx_cq->id, false, work_done); + } + return work_done; +} + +/* For TX we don't honour budget; consume everything */ +int be_poll_tx(struct napi_struct *napi, int budget) +{ + struct be_eq_obj *tx_eq = container_of(napi, struct be_eq_obj, napi); + struct be_adapter *adapter = + container_of(tx_eq, struct be_adapter, tx_eq); + struct be_tx_obj *tx_obj = &adapter->tx_obj; + struct be_queue_info *tx_cq = &tx_obj->cq; + struct be_queue_info *txq = &tx_obj->q; + struct be_eth_tx_compl *txcp; + u32 num_cmpl = 0; + u16 end_idx; + + while ((txcp = be_tx_compl_get(adapter))) { + end_idx = AMAP_GET_BITS(struct amap_eth_tx_compl, + wrb_index, txcp); + be_tx_compl_process(adapter, end_idx); + num_cmpl++; + } + + /* As Tx wrbs have been freed up, wake up netdev queue if + * it was stopped due to lack of tx wrbs. + */ + if (netif_queue_stopped(adapter->netdev) && + atomic_read(&txq->used) < txq->len / 2) { + netif_wake_queue(adapter->netdev); + } + + napi_complete(napi); + + be_cq_notify(&adapter->ctrl, tx_cq->id, true, num_cmpl); + + drvr_stats(adapter)->be_tx_events++; + drvr_stats(adapter)->be_tx_compl += num_cmpl; + + return 1; +} + +static void be_msix_enable(struct be_adapter *adapter) +{ + int i, status; + + for (i = 0; i < BE_NUM_MSIX_VECTORS; i++) + adapter->msix_entries[i].entry = i; + + status = pci_enable_msix(adapter->pdev, adapter->msix_entries, + BE_NUM_MSIX_VECTORS); + if (status == 0) + adapter->msix_enabled = true; + return; +} + +static inline int be_msix_vec_get(struct be_adapter *adapter, u32 eq_id) +{ + return adapter->msix_entries[eq_id - + 8 * adapter->ctrl.pci_func].vector; +} + +static int be_msix_register(struct be_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + int status, vec; + + sprintf(tx_eq->desc, "%s-tx", netdev->name); + vec = be_msix_vec_get(adapter, tx_eq->q.id); + status = request_irq(vec, be_msix_tx, 0, tx_eq->desc, adapter); + if (status) + goto err; + + sprintf(rx_eq->desc, "%s-rx", netdev->name); + vec = be_msix_vec_get(adapter, rx_eq->q.id); + status = request_irq(vec, be_msix_rx, 0, rx_eq->desc, adapter); + if (status) { /* Free TX IRQ */ + vec = be_msix_vec_get(adapter, tx_eq->q.id); + free_irq(vec, adapter); + goto err; + } + return 0; +err: + dev_warn(&adapter->pdev->dev, + "MSIX Request IRQ failed - err %d\n", status); + pci_disable_msix(adapter->pdev); + adapter->msix_enabled = false; + return status; +} + +static int be_irq_register(struct be_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int status; + + if (adapter->msix_enabled) { + status = be_msix_register(adapter); + if (status == 0) + goto done; + } + + /* INTx */ + netdev->irq = adapter->pdev->irq; + status = request_irq(netdev->irq, be_intx, IRQF_SHARED, netdev->name, + adapter); + if (status) { + dev_err(&adapter->pdev->dev, + "INTx request IRQ failed - err %d\n", status); + return status; + } +done: + adapter->isr_registered = true; + return 0; +} + +static void be_irq_unregister(struct be_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + int vec; + + if (!adapter->isr_registered) + return; + + /* INTx */ + if (!adapter->msix_enabled) { + free_irq(netdev->irq, adapter); + goto done; + } + + /* MSIx */ + vec = be_msix_vec_get(adapter, adapter->tx_eq.q.id); + free_irq(vec, adapter); + vec = be_msix_vec_get(adapter, adapter->rx_eq.q.id); + free_irq(vec, adapter); +done: + adapter->isr_registered = false; + return; +} + +static int be_open(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + u32 if_flags; + int status; + + if_flags = BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PROMISCUOUS | + BE_IF_FLAGS_MCAST_PROMISCUOUS | BE_IF_FLAGS_UNTAGGED | + BE_IF_FLAGS_PASS_L3L4_ERRORS; + status = be_cmd_if_create(ctrl, if_flags, netdev->dev_addr, + false/* pmac_invalid */, &adapter->if_handle, + &adapter->pmac_id); + if (status != 0) + goto do_none; + + status = be_cmd_set_flow_control(ctrl, true, true); + if (status != 0) + goto if_destroy; + + status = be_tx_queues_create(adapter); + if (status != 0) + goto if_destroy; + + status = be_rx_queues_create(adapter); + if (status != 0) + goto tx_qs_destroy; + + /* First time posting */ + be_post_rx_frags(adapter); + + napi_enable(&rx_eq->napi); + napi_enable(&tx_eq->napi); + + be_irq_register(adapter); + + be_intr_set(ctrl, true); + + /* The evt queues are created in the unarmed state; arm them */ + be_eq_notify(ctrl, rx_eq->q.id, true, false, 0); + be_eq_notify(ctrl, tx_eq->q.id, true, false, 0); + + /* The compl queues are created in the unarmed state; arm them */ + be_cq_notify(ctrl, adapter->rx_obj.cq.id, true, 0); + be_cq_notify(ctrl, adapter->tx_obj.cq.id, true, 0); + + be_link_status_update(adapter); + + schedule_delayed_work(&adapter->work, msecs_to_jiffies(100)); + return 0; + +tx_qs_destroy: + be_tx_queues_destroy(adapter); +if_destroy: + be_cmd_if_destroy(ctrl, adapter->if_handle); +do_none: + return status; +} + +static int be_close(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_eq_obj *rx_eq = &adapter->rx_eq; + struct be_eq_obj *tx_eq = &adapter->tx_eq; + int vec; + + cancel_delayed_work(&adapter->work); + + netif_stop_queue(netdev); + netif_carrier_off(netdev); + adapter->link.speed = PHY_LINK_SPEED_ZERO; + + be_intr_set(ctrl, false); + + if (adapter->msix_enabled) { + vec = be_msix_vec_get(adapter, tx_eq->q.id); + synchronize_irq(vec); + vec = be_msix_vec_get(adapter, rx_eq->q.id); + synchronize_irq(vec); + } else { + synchronize_irq(netdev->irq); + } + be_irq_unregister(adapter); + + napi_disable(&rx_eq->napi); + napi_disable(&tx_eq->napi); + + be_rx_queues_destroy(adapter); + be_tx_queues_destroy(adapter); + + be_cmd_if_destroy(ctrl, adapter->if_handle); + return 0; +} + +static int be_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr, + void **ip_hdr, void **tcpudp_hdr, + u64 *hdr_flags, void *priv) +{ + struct ethhdr *eh; + struct vlan_ethhdr *veh; + struct iphdr *iph; + u8 *va = page_address(frag->page) + frag->page_offset; + unsigned long ll_hlen; + + prefetch(va); + eh = (struct ethhdr *)va; + *mac_hdr = eh; + ll_hlen = ETH_HLEN; + if (eh->h_proto != htons(ETH_P_IP)) { + if (eh->h_proto == htons(ETH_P_8021Q)) { + veh = (struct vlan_ethhdr *)va; + if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP)) + return -1; + + ll_hlen += VLAN_HLEN; + } else { + return -1; + } + } + *hdr_flags = LRO_IPV4; + iph = (struct iphdr *)(va + ll_hlen); + *ip_hdr = iph; + if (iph->protocol != IPPROTO_TCP) + return -1; + *hdr_flags |= LRO_TCP; + *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2); + + return 0; +} + +static void be_lro_init(struct be_adapter *adapter, struct net_device *netdev) +{ + struct net_lro_mgr *lro_mgr; + + lro_mgr = &adapter->rx_obj.lro_mgr; + lro_mgr->dev = netdev; + lro_mgr->features = LRO_F_NAPI; + lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; + lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; + lro_mgr->max_desc = BE_MAX_LRO_DESCRIPTORS; + lro_mgr->lro_arr = adapter->rx_obj.lro_desc; + lro_mgr->get_frag_header = be_get_frag_header; + lro_mgr->max_aggr = BE_MAX_FRAGS_PER_FRAME; +} + +static struct net_device_ops be_netdev_ops = { + .ndo_open = be_open, + .ndo_stop = be_close, + .ndo_start_xmit = be_xmit, + .ndo_get_stats = be_get_stats, + .ndo_set_rx_mode = be_set_multicast_list, + .ndo_set_mac_address = be_mac_addr_set, + .ndo_change_mtu = be_change_mtu, + .ndo_validate_addr = eth_validate_addr, + .ndo_vlan_rx_register = be_vlan_register, + .ndo_vlan_rx_add_vid = be_vlan_add_vid, + .ndo_vlan_rx_kill_vid = be_vlan_rem_vid, +}; + +static void be_netdev_init(struct net_device *netdev) +{ + struct be_adapter *adapter = netdev_priv(netdev); + + netdev->features |= NETIF_F_SG | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | + NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM | + NETIF_F_IPV6_CSUM | NETIF_F_TSO6; + + netdev->flags |= IFF_MULTICAST; + + BE_SET_NETDEV_OPS(netdev, &be_netdev_ops); + + SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); + + be_lro_init(adapter, netdev); + + netif_napi_add(netdev, &adapter->rx_eq.napi, be_poll_rx, + BE_NAPI_WEIGHT); + netif_napi_add(netdev, &adapter->tx_eq.napi, be_poll_tx, + BE_NAPI_WEIGHT); + + netif_carrier_off(netdev); + netif_stop_queue(netdev); +} + +static void be_unmap_pci_bars(struct be_adapter *adapter) +{ + struct be_ctrl_info *ctrl = &adapter->ctrl; + if (ctrl->csr) + iounmap(ctrl->csr); + if (ctrl->db) + iounmap(ctrl->db); + if (ctrl->pcicfg) + iounmap(ctrl->pcicfg); +} + +static int be_map_pci_bars(struct be_adapter *adapter) +{ + u8 __iomem *addr; + + addr = ioremap_nocache(pci_resource_start(adapter->pdev, 2), + pci_resource_len(adapter->pdev, 2)); + if (addr == NULL) + return -ENOMEM; + adapter->ctrl.csr = addr; + + addr = ioremap_nocache(pci_resource_start(adapter->pdev, 4), + 128 * 1024); + if (addr == NULL) + goto pci_map_err; + adapter->ctrl.db = addr; + + addr = ioremap_nocache(pci_resource_start(adapter->pdev, 1), + pci_resource_len(adapter->pdev, 1)); + if (addr == NULL) + goto pci_map_err; + adapter->ctrl.pcicfg = addr; + + return 0; +pci_map_err: + be_unmap_pci_bars(adapter); + return -ENOMEM; +} + + +static void be_ctrl_cleanup(struct be_adapter *adapter) +{ + struct be_dma_mem *mem = &adapter->ctrl.mbox_mem_alloced; + + be_unmap_pci_bars(adapter); + + if (mem->va) + pci_free_consistent(adapter->pdev, mem->size, + mem->va, mem->dma); +} + +/* Initialize the mbox required to send cmds to BE */ +static int be_ctrl_init(struct be_adapter *adapter) +{ + struct be_ctrl_info *ctrl = &adapter->ctrl; + struct be_dma_mem *mbox_mem_alloc = &ctrl->mbox_mem_alloced; + struct be_dma_mem *mbox_mem_align = &ctrl->mbox_mem; + int status; + u32 val; + + status = be_map_pci_bars(adapter); + if (status) + return status; + + mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16; + mbox_mem_alloc->va = pci_alloc_consistent(adapter->pdev, + mbox_mem_alloc->size, &mbox_mem_alloc->dma); + if (!mbox_mem_alloc->va) { + be_unmap_pci_bars(adapter); + return -1; + } + mbox_mem_align->size = sizeof(struct be_mcc_mailbox); + mbox_mem_align->va = PTR_ALIGN(mbox_mem_alloc->va, 16); + mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16); + memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox)); + spin_lock_init(&ctrl->cmd_lock); + + val = ioread32(ctrl->pcicfg + PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET); + ctrl->pci_func = (val >> MEMBAR_CTRL_INT_CTRL_PFUNC_SHIFT) & + MEMBAR_CTRL_INT_CTRL_PFUNC_MASK; + return 0; +} + +static void be_stats_cleanup(struct be_adapter *adapter) +{ + struct be_stats_obj *stats = &adapter->stats; + struct be_dma_mem *cmd = &stats->cmd; + + if (cmd->va) + pci_free_consistent(adapter->pdev, cmd->size, + cmd->va, cmd->dma); +} + +static int be_stats_init(struct be_adapter *adapter) +{ + struct be_stats_obj *stats = &adapter->stats; + struct be_dma_mem *cmd = &stats->cmd; + + cmd->size = sizeof(struct be_cmd_req_get_stats); + cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma); + if (cmd->va == NULL) + return -1; + return 0; +} + +static void __devexit be_remove(struct pci_dev *pdev) +{ + struct be_adapter *adapter = pci_get_drvdata(pdev); + if (!adapter) + return; + + unregister_netdev(adapter->netdev); + + be_stats_cleanup(adapter); + + be_ctrl_cleanup(adapter); + + if (adapter->msix_enabled) { + pci_disable_msix(adapter->pdev); + adapter->msix_enabled = false; + } + + pci_set_drvdata(pdev, NULL); + pci_release_regions(pdev); + pci_disable_device(pdev); + + free_netdev(adapter->netdev); +} + +static int be_hw_up(struct be_adapter *adapter) +{ + struct be_ctrl_info *ctrl = &adapter->ctrl; + int status; + + status = be_cmd_POST(ctrl); + if (status) + return status; + + status = be_cmd_get_fw_ver(ctrl, adapter->fw_ver); + if (status) + return status; + + status = be_cmd_query_fw_cfg(ctrl, &adapter->port_num); + return status; +} + +static int __devinit be_probe(struct pci_dev *pdev, + const struct pci_device_id *pdev_id) +{ + int status = 0; + struct be_adapter *adapter; + struct net_device *netdev; + struct be_ctrl_info *ctrl; + u8 mac[ETH_ALEN]; + + status = pci_enable_device(pdev); + if (status) + goto do_none; + + status = pci_request_regions(pdev, DRV_NAME); + if (status) + goto disable_dev; + pci_set_master(pdev); + + netdev = alloc_etherdev(sizeof(struct be_adapter)); + if (netdev == NULL) { + status = -ENOMEM; + goto rel_reg; + } + adapter = netdev_priv(netdev); + adapter->pdev = pdev; + pci_set_drvdata(pdev, adapter); + adapter->netdev = netdev; + + be_msix_enable(adapter); + + status = pci_set_dma_mask(pdev, DMA_64BIT_MASK); + if (!status) { + netdev->features |= NETIF_F_HIGHDMA; + } else { + status = pci_set_dma_mask(pdev, DMA_32BIT_MASK); + if (status) { + dev_err(&pdev->dev, "Could not set PCI DMA Mask\n"); + goto free_netdev; + } + } + + ctrl = &adapter->ctrl; + status = be_ctrl_init(adapter); + if (status) + goto free_netdev; + + status = be_stats_init(adapter); + if (status) + goto ctrl_clean; + + status = be_hw_up(adapter); + if (status) + goto stats_clean; + + status = be_cmd_mac_addr_query(ctrl, mac, MAC_ADDRESS_TYPE_NETWORK, + true /* permanent */, 0); + if (status) + goto stats_clean; + memcpy(netdev->dev_addr, mac, ETH_ALEN); + + INIT_DELAYED_WORK(&adapter->work, be_worker); + be_netdev_init(netdev); + SET_NETDEV_DEV(netdev, &adapter->pdev->dev); + + status = register_netdev(netdev); + if (status != 0) + goto stats_clean; + + dev_info(&pdev->dev, BE_NAME " port %d\n", adapter->port_num); + return 0; + +stats_clean: + be_stats_cleanup(adapter); +ctrl_clean: + be_ctrl_cleanup(adapter); +free_netdev: + free_netdev(adapter->netdev); +rel_reg: + pci_release_regions(pdev); +disable_dev: + pci_disable_device(pdev); +do_none: + dev_warn(&pdev->dev, BE_NAME " initialization failed\n"); + return status; +} + +static int be_suspend(struct pci_dev *pdev, pm_message_t state) +{ + struct be_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + + netif_device_detach(netdev); + if (netif_running(netdev)) { + rtnl_lock(); + be_close(netdev); + rtnl_unlock(); + } + + pci_save_state(pdev); + pci_disable_device(pdev); + pci_set_power_state(pdev, pci_choose_state(pdev, state)); + return 0; +} + +static int be_resume(struct pci_dev *pdev) +{ + int status = 0; + struct be_adapter *adapter = pci_get_drvdata(pdev); + struct net_device *netdev = adapter->netdev; + + netif_device_detach(netdev); + + status = pci_enable_device(pdev); + if (status) + return status; + + pci_set_power_state(pdev, 0); + pci_restore_state(pdev); + + be_vids_config(netdev); + + if (netif_running(netdev)) { + rtnl_lock(); + be_open(netdev); + rtnl_unlock(); + } + netif_device_attach(netdev); + return 0; +} + +static struct pci_driver be_driver = { + .name = DRV_NAME, + .id_table = be_dev_ids, + .probe = be_probe, + .remove = be_remove, + .suspend = be_suspend, + .resume = be_resume +}; + +static int __init be_init_module(void) +{ + if (rx_frag_size != 8192 && rx_frag_size != 4096 + && rx_frag_size != 2048) { + printk(KERN_WARNING DRV_NAME + " : Module param rx_frag_size must be 2048/4096/8192." + " Using 2048\n"); + rx_frag_size = 2048; + } + /* Ensure rx_frag_size is aligned to chache line */ + if (SKB_DATA_ALIGN(rx_frag_size) != rx_frag_size) { + printk(KERN_WARNING DRV_NAME + " : Bad module param rx_frag_size. Using 2048\n"); + rx_frag_size = 2048; + } + + return pci_register_driver(&be_driver); +} +module_init(be_init_module); + +static void __exit be_exit_module(void) +{ + pci_unregister_driver(&be_driver); +} +module_exit(be_exit_module); -- cgit v1.2.3 From 3bb9db79235e19dbb18ba6f4a428a97c69115319 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 12 Mar 2009 13:36:38 +0100 Subject: hwmon: (abituguru3) Fix I/O error handling Fix a logic bug reported by Roel Kluin, by rewriting the error handling code in a clearer way. Signed-off-by: Jean Delvare Cc: Roel Kluin Acked-by: Alistair John Strachan Acked-by: Hans de Goede --- drivers/hwmon/abituguru3.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index e52b38806d03..ad2b3431b725 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -760,8 +760,11 @@ static int abituguru3_read_increment_offset(struct abituguru3_data *data, for (i = 0; i < offset_count; i++) if ((x = abituguru3_read(data, bank, offset + i, count, - buf + i * count)) != count) - return i * count + (i && (x < 0)) ? 0 : x; + buf + i * count)) != count) { + if (x < 0) + return x; + return i * count + x; + } return i * count; } -- cgit v1.2.3 From 1a51e068c900eb6ea23ce597361ebf3b19a57b23 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 12 Mar 2009 13:36:38 +0100 Subject: hwmon: (lm90) Document support for the MAX6648/6692 chips Update documentation to prevent further confusion/duplication. Signed-off-by: Darrick J. Wong Signed-off-by: Jean Delvare --- Documentation/hwmon/lm90 | 10 ++++++++++ drivers/hwmon/Kconfig | 4 ++-- drivers/hwmon/lm90.c | 8 ++++---- 3 files changed, 16 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/Documentation/hwmon/lm90 b/Documentation/hwmon/lm90 index 0e8411710238..93d8e3d55150 100644 --- a/Documentation/hwmon/lm90 +++ b/Documentation/hwmon/lm90 @@ -42,6 +42,11 @@ Supported chips: Addresses scanned: I2C 0x4e Datasheet: Publicly available at the Maxim website http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3497 + * Maxim MAX6648 + Prefix: 'max6646' + Addresses scanned: I2C 0x4c + Datasheet: Publicly available at the Maxim website + http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3500 * Maxim MAX6649 Prefix: 'max6646' Addresses scanned: I2C 0x4c @@ -74,6 +79,11 @@ Supported chips: 0x4c, 0x4d and 0x4e Datasheet: Publicly available at the Maxim website http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3370 + * Maxim MAX6692 + Prefix: 'max6646' + Addresses scanned: I2C 0x4c + Datasheet: Publicly available at the Maxim website + http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3500 Author: Jean Delvare diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index b84bf066879b..b4eea0292c1a 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -543,8 +543,8 @@ config SENSORS_LM90 help If you say yes here you get support for National Semiconductor LM90, LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, and Maxim - MAX6646, MAX6647, MAX6649, MAX6657, MAX6658, MAX6659, MAX6680 and - MAX6681 sensor chips. + MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659, + MAX6680, MAX6681 and MAX6692 sensor chips. This driver can also be built as a module. If so, the module will be called lm90. diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 96a701866726..1aff7575799d 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -32,10 +32,10 @@ * supported by this driver. These chips lack the remote temperature * offset feature. * - * This driver also supports the MAX6646, MAX6647 and MAX6649 chips - * made by Maxim. These are again similar to the LM86, but they use - * unsigned temperature values and can report temperatures from 0 to - * 145 degrees. + * This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and + * MAX6692 chips made by Maxim. These are again similar to the LM86, + * but they use unsigned temperature values and can report temperatures + * from 0 to 145 degrees. * * This driver also supports the MAX6680 and MAX6681, two other sensor * chips made by Maxim. These are quite similar to the other Maxim -- cgit v1.2.3 From e267d25005c861fe6afda343f044536342c9f8b4 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 12 Mar 2009 13:36:39 +0100 Subject: hwmon: (it87) Properly decode -128 degrees C temperature The it87 driver is reporting -128 degrees C as +128 degrees C. That's not a terribly likely temperature value but let's still get it right, especially when it simplifies the code. Signed-off-by: Jean Delvare --- drivers/hwmon/it87.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 95a99c590da2..9157247fed8e 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -213,7 +213,7 @@ static inline u16 FAN16_TO_REG(long rpm) #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-500)/1000):\ ((val)+500)/1000),-128,127)) -#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*1000) +#define TEMP_FROM_REG(val) ((val) * 1000) #define PWM_TO_REG(val) ((val) >> 1) #define PWM_FROM_REG(val) (((val)&0x7f) << 1) @@ -267,9 +267,9 @@ struct it87_data { u8 has_fan; /* Bitfield, fans enabled */ u16 fan[5]; /* Register values, possibly combined */ u16 fan_min[5]; /* Register values, possibly combined */ - u8 temp[3]; /* Register value */ - u8 temp_high[3]; /* Register value */ - u8 temp_low[3]; /* Register value */ + s8 temp[3]; /* Register value */ + s8 temp_high[3]; /* Register value */ + s8 temp_low[3]; /* Register value */ u8 sensor; /* Register value */ u8 fan_div[3]; /* Register encoding, shifted right */ u8 vid; /* Register encoding, combined */ -- cgit v1.2.3 From 51b3e2700177b89fdb0d985926ce777a7ad52b15 Mon Sep 17 00:00:00 2001 From: Andrew Klossner Date: Thu, 12 Mar 2009 13:36:39 +0100 Subject: hwmon: (f75375s) Remove unnecessary and confusing initialization f75375_probe calls i2c_get_clientdata to initialize the data pointer, but there isn't yet any client data to get, and the value is never used before the variable is assigned a new value seven lines later. The call doesn't hurt anything and wastes only a couple of cycles. The reason to fix it is because this module serves as an example to hackers writing new hwmon drivers, and this part of the example is confusing. Signed-off-by: Andrew Klossner Signed-off-by: Jean Delvare --- drivers/hwmon/f75375s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 1692de369969..18a1ba888165 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -617,7 +617,7 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data, static int f75375_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct f75375_data *data = i2c_get_clientdata(client); + struct f75375_data *data; struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data; int err; -- cgit v1.2.3 From 649426efcfbc67a8b033497151816cbac9fd0cfa Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 5 Mar 2009 13:57:28 -0500 Subject: PCI: Add PCI quirk to disable L0s ASPM state for 82575 and 82598 This patch is intended to disable L0s ASPM link state for 82598 (ixgbe) parts due to the fact that it is possible to corrupt TX data when coming back out of L0s on some systems. The workaround had been added for 82575 (igb) previously, but did not use the ASPM api. This quirk uses the ASPM api to prevent the ASPM subsystem from re-enabling the L0s state. Instead of adding the fix in igb to the ixgbe driver as well it was decided to move it into a pci quirk. It is necessary to move the fix out of the driver and into a pci quirk in order to prevent the issue from occuring prior to driver load to handle the possibility of the device being passed to a VM via direct assignment. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher CC: Jesse Barnes Signed-off-by: Matthew Wilcox --- drivers/pci/quirks.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index f20d55368edb..1a7c48d71dc7 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "pci.h" int isa_dma_bridge_buggy; @@ -1749,6 +1750,30 @@ static void __devinit quirk_e100_interrupt(struct pci_dev *dev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_e100_interrupt); +/* + * The 82575 and 82598 may experience data corruption issues when transitioning + * out of L0S. To prevent this we need to disable L0S on the pci-e link + */ +static void __devinit quirk_disable_aspm_l0s(struct pci_dev *dev) +{ + dev_info(&dev->dev, "Disabling L0s\n"); + pci_disable_link_state(dev, PCIE_LINK_STATE_L0S); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10a7, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10a9, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10b6, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10c6, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10c7, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10c8, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10d6, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10db, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10dd, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10e1, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10ec, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f1, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s); + static void __devinit fixup_rev1_53c810(struct pci_dev* dev) { /* rev 1 ncr53c810 chips don't set the class at all which means -- cgit v1.2.3 From cb4cb4ac7338c28b047760be187355ed9c783e72 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Thu, 5 Mar 2009 19:28:40 -0700 Subject: PCIe: AER: during disable, check subordinate before walking Commit 47a8b0cc (Enable PCIe AER only after checking firmware support) wants to walk the PCI bus in the remove path to disable AER, and calls pci_walk_bus for downstream bridges. Unfortunately, in the remove path, we remove devices and bridges in a depth-first manner, starting with the furthest downstream bridge and working our way backwards. The furthest downstream bridges will not have a dev->subordinate, and we hit a NULL deref in pci_walk_bus. Check for dev->subordinate first before attempting to walk the PCI hierarchy below us. Acked-by: Andrew Patterson Signed-off-by: Alex Chiang Signed-off-by: Matthew Wilcox --- drivers/pci/pcie/aer/aerdrv_core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index d0c973685868..382575007382 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -133,6 +133,9 @@ static void set_downstream_devices_error_reporting(struct pci_dev *dev, bool enable) { set_device_error_reporting(dev, &enable); + + if (!dev->subordinate) + return; pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable); } -- cgit v1.2.3 From 3f3b902ed8147c42a4a9764014c758e6b3f42f51 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 6 Mar 2009 14:39:14 +1100 Subject: powerpc/pseries: The RPA PCI hotplug driver depends on EEH The RPA PCI hotplug driver calls EEH routines, so should depend on EEH. Also PPC_PSERIES implies PPC64, so remove that. Signed-off-by: Michael Ellerman Signed-off-by: Matthew Wilcox --- drivers/pci/hotplug/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index eacfb13998bb..9aa4fe100a0d 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig @@ -143,7 +143,7 @@ config HOTPLUG_PCI_SHPC config HOTPLUG_PCI_RPA tristate "RPA PCI Hotplug driver" - depends on PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE + depends on PPC_PSERIES && EEH && !HOTPLUG_PCI_FAKE help Say Y here if you have a RPA system that supports PCI Hotplug. -- cgit v1.2.3 From 7726c3308a92b4a4c3bd059059498fca0e6f8e48 Mon Sep 17 00:00:00 2001 From: Prakash Punnoor Date: Fri, 6 Mar 2009 00:45:12 +0100 Subject: pci: don't disable too many HT MSI mapping Prakash's system needs MSI disabled on some bridges, but not all. This seems to be the minimal fix for 2.6.29, but should be replaced during 2.6.30. Signed-off-by: Prakash Punnoor Signed-off-by: Matthew Wilcox --- drivers/pci/quirks.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 1a7c48d71dc7..9104671e4b72 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2166,6 +2166,10 @@ static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) int pos; int found; + /* Enabling HT MSI mapping on this device breaks MCP51 */ + if (dev->device == 0x270) + return; + /* check if there is HT MSI cap or enabled on this device */ found = ht_check_msi_mapping(dev); -- cgit v1.2.3 From 6a958d5b28e4a180458e0d319d2e4bb5c4b7da3e Mon Sep 17 00:00:00 2001 From: Prakash Punnoor Date: Fri, 6 Mar 2009 10:10:35 +0100 Subject: pci: Fix typo in message while disabling HT MSI mapping "Enabling" should read "Disabling" Signed-off-by: Prakash Punnoor Signed-off-by: Matthew Wilcox --- drivers/pci/quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 9104671e4b72..92b9efe9bcaf 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2122,7 +2122,7 @@ static void __devinit ht_disable_msi_mapping(struct pci_dev *dev) if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, &flags) == 0) { - dev_info(&dev->dev, "Enabling HT MSI Mapping\n"); + dev_info(&dev->dev, "Disabling HT MSI Mapping\n"); pci_write_config_byte(dev, pos + HT_MSI_FLAGS, flags & ~HT_MSI_FLAGS_ENABLE); -- cgit v1.2.3 From d89987193631bf23d1735c55d13a06d4b8d0e9bd Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sat, 7 Mar 2009 19:35:47 -0700 Subject: PCIe: portdrv: call pci_disable_device during remove The PCIe port driver calls pci_enable_device() during probe but never calls pci_disable_device() during remove. Cc: stable@kernel.org Signed-off-by: Alex Chiang Signed-off-by: Matthew Wilcox --- drivers/pci/pcie/portdrv_pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 248b4db91552..5ea566e20b37 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -103,6 +103,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev, static void pcie_portdrv_remove (struct pci_dev *dev) { pcie_port_device_remove(dev); + pci_disable_device(dev); kfree(pci_get_drvdata(dev)); } -- cgit v1.2.3 From 8d0df7a3d1ecbaf5d5602a59055c8ca993855bed Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 12 Mar 2009 14:31:25 -0700 Subject: drivers/w1/masters/w1-gpio.c: fix read_bit() W1 master implementations are expected to return 0 or 1 from their read_bit() function. However, not all platforms do return these values from gpio_get_value() - namely PXAs won't. Hence the w1 gpio-master needs to break the result down to 0 or 1 itself. Signed-off-by: Daniel Mack Cc: Ville Syrjala Cc: Evgeniy Polyakov Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/w1/masters/w1-gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c index 9e1138a75e8b..a411702413d6 100644 --- a/drivers/w1/masters/w1-gpio.c +++ b/drivers/w1/masters/w1-gpio.c @@ -39,7 +39,7 @@ static u8 w1_gpio_read_bit(void *data) { struct w1_gpio_platform_data *pdata = data; - return gpio_get_value(pdata->pin); + return gpio_get_value(pdata->pin) ? 1 : 0; } static int __init w1_gpio_probe(struct platform_device *pdev) -- cgit v1.2.3 From a4e3f91b98d86ae0b5c816fe45190bb29ac32f71 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 12 Mar 2009 14:31:30 -0700 Subject: ds2760_battery.c: fix division by zero The 'battery remaining capacity' calculation in drivers/power/ds2760_battery.c lacks a parameter check to a division operation which causes the kernel to oops on my board. [ 21.233750] Division by zero in kernel. [ 21.237646] [] (__div0+0x0/0x20) from [] (Ldiv0+0x8/0x10) [ 21.244816] [] (ds2760_battery_read_status+0x0/0x2a4) from [] (ds2760_battery_get_property+0x30/0xdc) [ 21.255803] r8:c03a22c0 r7:c7886100 r6:00000009 r5:c782fe7c r4:c7886084 [ 21.262518] [] (ds2760_battery_get_property+0x0/0xdc) from [] (power_supply_show_property+0x48/0x114) [ 21.273480] r6:c7996000 r5:00000009 r4:00000000 [ 21.278111] [] (power_supply_show_property+0x0/0x114) from [] (power_supply_uevent+0x188/0x280) [ 21.288537] r8:00000001 r7:c7886100 r6:c7996000 r5:000000b4 r4:00000000 [ 21.295222] [] (power_supply_uevent+0x0/0x280) from [] (dev_uevent+0xd4/0x10c) [ 21.304199] [] (dev_uevent+0x0/0x10c) from [] (kobject_uevent_env+0x180/0x390) [ 21.313170] r5:00000000 r4:c78860ac [ 21.316725] [] (kobject_uevent_env+0x0/0x390) from [] (kobject_uevent+0x14/0x18) [ 21.325850] [] (kobject_uevent+0x0/0x18) from [] (power_supply_changed_work+0x5c/0x70) [ 21.335506] [] (power_supply_changed_work+0x0/0x70) from [] (run_workqueue+0xbc/0x144) [ 21.345167] r4:c7812040 [ 21.347716] [] (run_workqueue+0x0/0x144) from [] (worker_thread+0xa8/0xbc) [ 21.356296] r7:c7812040 r6:c7820b00 r5:c782ffa4 r4:c7812048 [ 21.361957] [] (worker_thread+0x0/0xbc) from [] (kthread+0x5c/0x94) [ 21.369971] r7:00000000 r6:c004d8a4 r5:c7812040 r4:c782e000 [ 21.375612] [] (kthread+0x0/0x94) from [] (do_exit+0x0/0x688) Signed-off-by: Daniel Mack Cc: Szabolcs Gyurko Acked-by: Matt Reimer Acked-by: Anton Vorontsov Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/power/ds2760_battery.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c index 1d768928e0bb..a52d4a11652d 100644 --- a/drivers/power/ds2760_battery.c +++ b/drivers/power/ds2760_battery.c @@ -180,10 +180,13 @@ static int ds2760_battery_read_status(struct ds2760_device_info *di) di->empty_uAh = battery_interpolate(scale, di->temp_C / 10); di->empty_uAh *= 1000; /* convert to µAh */ - /* From Maxim Application Note 131: remaining capacity = - * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */ - di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) / - (di->full_active_uAh - di->empty_uAh); + if (di->full_active_uAh == di->empty_uAh) + di->rem_capacity = 0; + else + /* From Maxim Application Note 131: remaining capacity = + * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */ + di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) / + (di->full_active_uAh - di->empty_uAh); if (di->rem_capacity < 0) di->rem_capacity = 0; -- cgit v1.2.3 From 7c48ed3383bfb2106694807361ec187fe8a4333d Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 12 Mar 2009 14:31:33 -0700 Subject: mmc: s3cmci: fix s3c2410_dma_config() arguments. The s3cmci driver is calling s3c2410_dma_config with incorrect data for the DCON register. The S3C2410_DCON_HWTRIG is implicit in the channel configuration and the device selection of S3C2410_DCON_CH0_SDI is incorrect as the DMA system may not select channel 0. Signed-off-by: Ben Dooks Acked-by: Pierre Ossman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mmc/host/s3cmci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index f4a67c65d301..2db166b7096f 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -793,8 +793,7 @@ static void s3cmci_dma_setup(struct s3cmci_host *host, host->mem->start + host->sdidata); if (!setup_ok) { - s3c2410_dma_config(host->dma, 4, - (S3C2410_DCON_HWTRIG | S3C2410_DCON_CH0_SDI)); + s3c2410_dma_config(host->dma, 4, 0); s3c2410_dma_set_buffdone_fn(host->dma, s3cmci_dma_done_callback); s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART); -- cgit v1.2.3 From 1ba869ec581fd9078b684c56c399ffe3d2345e27 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Thu, 12 Mar 2009 14:31:34 -0700 Subject: acer-wmi: fix regression in backlight detection Currently we disable the Acer WMI backlight device if there is no ACPI backlight device. As a result, we end up with no backlight device at all. We should instead disable it if there is an ACPI device, as the other laptop drivers do. This regression was introduced in febf2d9 ("Acer-WMI: fingers off backlight if video.ko is serving this functionality"). Each laptop driver with backlight support got a similar change around febf2d9. The changes to the other drivers look correct; see e.g. a598c82f for a similar but correct change. The regression is also in 2.6.28. Signed-off-by: Michael Spang Acked-by: Thomas Renninger Cc: Zhang Rui Cc: Andi Kleen Cc: Carlos Corbacho Cc: Len Brown Cc: "Rafael J. Wysocki" Cc: [2.6.28.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/platform/x86/acer-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 94c9f911824e..6bcca616a704 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1297,7 +1297,7 @@ static int __init acer_wmi_init(void) set_quirks(); - if (!acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { + if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { interface->capability &= ~ACER_CAP_BRIGHTNESS; printk(ACER_INFO "Brightness must be controlled by " "generic video driver\n"); -- cgit v1.2.3 From 02d46e07e538c285accb5c000a7db3a97eff1fbf Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 12 Mar 2009 14:31:36 -0700 Subject: mfd: add support for WM8351 revision B No software visible difference from revision A. Signed-off-by: Mark Brown Cc: Samuel Ortiz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mfd/wm8350-core.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index 84d5ea1ec171..b457a05b28d9 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c @@ -1383,6 +1383,11 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, wm8350->power.rev_g_coeff = 1; break; + case 1: + dev_info(wm8350->dev, "WM8351 Rev B\n"); + wm8350->power.rev_g_coeff = 1; + break; + default: dev_err(wm8350->dev, "Unknown WM8351 CHIP_REV\n"); ret = -ENODEV; -- cgit v1.2.3 From c12e56ef6951f4fce1afe9ef6aab9243ea9a9b04 Mon Sep 17 00:00:00 2001 From: Faisal Latif Date: Thu, 12 Mar 2009 14:34:59 -0700 Subject: RDMA/nes: Don't allow userspace QPs to use STag zero STag zero is a special STag that allows consumers to access any bus address without registering memory. The nes driver unfortunately allows STag zero to be used even with QPs created by unprivileged userspace consumers, which means that any process with direct verbs access to the nes device can read and write any memory accessible to the underlying PCI device (usually any memory in the system). Such access is usually given for cluster software such as MPI to use, so this is a local privilege escalation bug on most systems running this driver. The driver was using STag zero to receive the last streaming mode data; to allow STag zero to be disabled for unprivileged QPs, the driver now registers a special MR for this data. Cc: Signed-off-by: Faisal Latif Signed-off-by: Roland Dreier Signed-off-by: Linus Torvalds --- drivers/infiniband/hw/nes/nes_cm.c | 39 ++++++++++++++++++++++++++++++----- drivers/infiniband/hw/nes/nes_verbs.c | 2 ++ drivers/infiniband/hw/nes/nes_verbs.h | 1 + 3 files changed, 37 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index a01b4488208b..4a65b96db2c8 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -2490,12 +2490,14 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt) int ret = 0; struct nes_vnic *nesvnic; struct nes_device *nesdev; + struct nes_ib_device *nesibdev; nesvnic = to_nesvnic(nesqp->ibqp.device); if (!nesvnic) return -EINVAL; nesdev = nesvnic->nesdev; + nesibdev = nesvnic->nesibdev; nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n", atomic_read(&nesvnic->netdev->refcnt)); @@ -2507,6 +2509,8 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt) } else { /* Need to free the Last Streaming Mode Message */ if (nesqp->ietf_frame) { + if (nesqp->lsmm_mr) + nesibdev->ibdev.dereg_mr(nesqp->lsmm_mr); pci_free_consistent(nesdev->pcidev, nesqp->private_data_len+sizeof(struct ietf_mpa_frame), nesqp->ietf_frame, nesqp->ietf_frame_pbase); @@ -2543,6 +2547,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) u32 crc_value; int ret; int passive_state; + struct nes_ib_device *nesibdev; + struct ib_mr *ibmr = NULL; + struct ib_phys_buf ibphysbuf; + struct nes_pd *nespd; + + ibqp = nes_get_qp(cm_id->device, conn_param->qpn); if (!ibqp) @@ -2601,6 +2611,26 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) if (cm_id->remote_addr.sin_addr.s_addr != cm_id->local_addr.sin_addr.s_addr) { u64temp = (unsigned long)nesqp; + nesibdev = nesvnic->nesibdev; + nespd = nesqp->nespd; + ibphysbuf.addr = nesqp->ietf_frame_pbase; + ibphysbuf.size = conn_param->private_data_len + + sizeof(struct ietf_mpa_frame); + ibmr = nesibdev->ibdev.reg_phys_mr((struct ib_pd *)nespd, + &ibphysbuf, 1, + IB_ACCESS_LOCAL_WRITE, + (u64 *)&nesqp->ietf_frame); + if (!ibmr) { + nes_debug(NES_DBG_CM, "Unable to register memory region" + "for lSMM for cm_node = %p \n", + cm_node); + return -ENOMEM; + } + + ibmr->pd = &nespd->ibpd; + ibmr->device = nespd->ibpd.device; + nesqp->lsmm_mr = ibmr; + u64temp |= NES_SW_CONTEXT_ALIGN>>1; set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, @@ -2611,14 +2641,13 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame)); - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = - cpu_to_le32((u32)nesqp->ietf_frame_pbase); - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = - cpu_to_le32((u32)((u64)nesqp->ietf_frame_pbase >> 32)); + set_wqe_64bit_value(wqe->wqe_words, + NES_IWARP_SQ_WQE_FRAG0_LOW_IDX, + (u64)nesqp->ietf_frame); wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame)); - wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; + wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = ibmr->lkey; nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 4fdb72454f94..d93a6562817c 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1360,8 +1360,10 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, NES_QPCONTEXT_MISC_RQ_SIZE_SHIFT); nesqp->nesqp_context->misc |= cpu_to_le32((u32)nesqp->hwqp.sq_encoded_size << NES_QPCONTEXT_MISC_SQ_SIZE_SHIFT); + if (!udata) { nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_PRIV_EN); nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_FAST_REGISTER_EN); + } nesqp->nesqp_context->cqs = cpu_to_le32(nesqp->nesscq->hw_cq.cq_number + ((u32)nesqp->nesrcq->hw_cq.cq_number << 16)); u64temp = (u64)nesqp->hwqp.sq_pbase; diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h index 6c6b4da5184f..ae0ca9bc83bd 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.h +++ b/drivers/infiniband/hw/nes/nes_verbs.h @@ -134,6 +134,7 @@ struct nes_qp { struct ietf_mpa_frame *ietf_frame; dma_addr_t ietf_frame_pbase; wait_queue_head_t state_waitq; + struct ib_mr *lsmm_mr; unsigned long socket; struct nes_hw_qp hwqp; struct work_struct work; -- cgit v1.2.3 From 5f77af93266e107bd46c010c51d772c0fb003232 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 10 Mar 2009 13:06:40 -0300 Subject: V4L/DVB (10972): zl10353: i2c_gate_ctrl bug fix zl10353 i2c-gate was always closed and due to that devices having tuner behind i2c-gate were broken. Add module configuration which allows disabling i2c-gate only when really needed. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/zl10353.c | 2 +- drivers/media/dvb/frontends/zl10353.h | 3 +++ drivers/media/video/saa7134/saa7134-dvb.c | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c index 170720b02815..b150ed306696 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb/frontends/zl10353.c @@ -590,7 +590,7 @@ static int zl10353_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) struct zl10353_state *state = fe->demodulator_priv; u8 val = 0x0a; - if (state->config.no_tuner) { + if (state->config.disable_i2c_gate_ctrl) { /* No tuner attached to the internal I2C bus */ /* If set enable I2C bridge, the main I2C bus stopped hardly */ return 0; diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h index fdbb88ff75fe..2287bac46243 100644 --- a/drivers/media/dvb/frontends/zl10353.h +++ b/drivers/media/dvb/frontends/zl10353.h @@ -38,6 +38,9 @@ struct zl10353_config /* set if parallel ts output is required */ int parallel_ts; + + /* set if i2c_gate_ctrl disable is required */ + u8 disable_i2c_gate_ctrl:1; }; #if defined(CONFIG_DVB_ZL10353) || (defined(CONFIG_DVB_ZL10353_MODULE) && defined(MODULE)) diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 0776ecf56d27..b5370b3e1a3d 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -860,6 +860,7 @@ static struct zl10353_config behold_h6_config = { .demod_address = 0x1e>>1, .no_tuner = 1, .parallel_ts = 1, + .disable_i2c_gate_ctrl = 1, }; /* ================================================================== -- cgit v1.2.3 From f507cd22035fdadd5dbb476dd05e9e7ee21c3b84 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 6 Mar 2009 02:54:09 +0000 Subject: ps3/block: Replace mtd/ps3vram by block/ps3vram Convert the PS3 Video RAM Storage Driver from an MTD driver to a plain block device driver. The ps3vram driver exposes unused video RAM on the PS3 as a block device suitable for storage or swap. Fast data transfer is achieved using a local cache in system RAM and DMA transfers via the GPU. The new driver is ca. 50% faster for reading, and ca. 10% for writing. Signed-off-by: Geert Uytterhoeven Acked-by: Geoff Levand Signed-off-by: Benjamin Herrenschmidt --- arch/powerpc/platforms/ps3/Kconfig | 7 + drivers/block/Makefile | 1 + drivers/block/ps3vram.c | 865 +++++++++++++++++++++++++++++++++++++ drivers/mtd/devices/Kconfig | 7 - drivers/mtd/devices/Makefile | 1 - drivers/mtd/devices/ps3vram.c | 768 -------------------------------- 6 files changed, 873 insertions(+), 776 deletions(-) create mode 100644 drivers/block/ps3vram.c delete mode 100644 drivers/mtd/devices/ps3vram.c (limited to 'drivers') diff --git a/arch/powerpc/platforms/ps3/Kconfig b/arch/powerpc/platforms/ps3/Kconfig index 920cf7a454b1..740ef56a1550 100644 --- a/arch/powerpc/platforms/ps3/Kconfig +++ b/arch/powerpc/platforms/ps3/Kconfig @@ -128,6 +128,13 @@ config PS3_FLASH be disabled on the kernel command line using "ps3flash=off", to not allocate this fixed buffer. +config PS3_VRAM + tristate "PS3 Video RAM Storage Driver" + depends on FB_PS3=y && BLOCK && m + help + This driver allows you to use excess PS3 video RAM as volatile + storage or system swap. + config PS3_LPM tristate "PS3 Logical Performance Monitor support" depends on PPC_PS3 diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 204332b29578..87e120e0a79c 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_MAC_FLOPPY) += swim3.o obj-$(CONFIG_BLK_DEV_FD) += floppy.o obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o obj-$(CONFIG_PS3_DISK) += ps3disk.o +obj-$(CONFIG_PS3_VRAM) += ps3vram.o obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o obj-$(CONFIG_BLK_DEV_RAM) += brd.o diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c new file mode 100644 index 000000000000..393ed6760d78 --- /dev/null +++ b/drivers/block/ps3vram.c @@ -0,0 +1,865 @@ +/* + * ps3vram - Use extra PS3 video ram as MTD block device. + * + * Copyright 2009 Sony Corporation + * + * Based on the MTD ps3vram driver, which is + * Copyright (c) 2007-2008 Jim Paris + * Added support RSX DMA Vivien Chappelier + */ + +#include +#include +#include +#include + +#include +#include +#include + + +#define DEVICE_NAME "ps3vram" + + +#define XDR_BUF_SIZE (2 * 1024 * 1024) /* XDR buffer (must be 1MiB aligned) */ +#define XDR_IOIF 0x0c000000 + +#define FIFO_BASE XDR_IOIF +#define FIFO_SIZE (64 * 1024) + +#define DMA_PAGE_SIZE (4 * 1024) + +#define CACHE_PAGE_SIZE (256 * 1024) +#define CACHE_PAGE_COUNT ((XDR_BUF_SIZE - FIFO_SIZE) / CACHE_PAGE_SIZE) + +#define CACHE_OFFSET CACHE_PAGE_SIZE +#define FIFO_OFFSET 0 + +#define CTRL_PUT 0x10 +#define CTRL_GET 0x11 +#define CTRL_TOP 0x15 + +#define UPLOAD_SUBCH 1 +#define DOWNLOAD_SUBCH 2 + +#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c +#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104 + +#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601 + +#define CACHE_PAGE_PRESENT 1 +#define CACHE_PAGE_DIRTY 2 + +struct ps3vram_tag { + unsigned int address; + unsigned int flags; +}; + +struct ps3vram_cache { + unsigned int page_count; + unsigned int page_size; + struct ps3vram_tag *tags; + unsigned int hit; + unsigned int miss; +}; + +struct ps3vram_priv { + struct request_queue *queue; + struct gendisk *gendisk; + + u64 size; + + u64 memory_handle; + u64 context_handle; + u32 *ctrl; + u32 *reports; + u8 __iomem *ddr_base; + u8 *xdr_buf; + + u32 *fifo_base; + u32 *fifo_ptr; + + struct ps3vram_cache cache; + + /* Used to serialize cache/DMA operations */ + struct mutex lock; +}; + + +static int ps3vram_major; + + +static struct block_device_operations ps3vram_fops = { + .owner = THIS_MODULE, +}; + + +#define DMA_NOTIFIER_HANDLE_BASE 0x66604200 /* first DMA notifier handle */ +#define DMA_NOTIFIER_OFFSET_BASE 0x1000 /* first DMA notifier offset */ +#define DMA_NOTIFIER_SIZE 0x40 +#define NOTIFIER 7 /* notifier used for completion report */ + +static char *size = "256M"; +module_param(size, charp, 0); +MODULE_PARM_DESC(size, "memory size"); + +static u32 *ps3vram_get_notifier(u32 *reports, int notifier) +{ + return (void *)reports + DMA_NOTIFIER_OFFSET_BASE + + DMA_NOTIFIER_SIZE * notifier; +} + +static void ps3vram_notifier_reset(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); + int i; + + for (i = 0; i < 4; i++) + notify[i] = 0xffffffff; +} + +static int ps3vram_notifier_wait(struct ps3_system_bus_device *dev, + unsigned int timeout_ms) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); + unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); + + do { + if (!notify[3]) + return 0; + msleep(1); + } while (time_before(jiffies, timeout)); + + return -ETIMEDOUT; +} + +static void ps3vram_init_ring(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; + priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET; +} + +static int ps3vram_wait_ring(struct ps3_system_bus_device *dev, + unsigned int timeout_ms) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); + + do { + if (priv->ctrl[CTRL_PUT] == priv->ctrl[CTRL_GET]) + return 0; + msleep(1); + } while (time_before(jiffies, timeout)); + + dev_warn(&dev->core, "FIFO timeout (%08x/%08x/%08x)\n", + priv->ctrl[CTRL_PUT], priv->ctrl[CTRL_GET], + priv->ctrl[CTRL_TOP]); + + return -ETIMEDOUT; +} + +static void ps3vram_out_ring(struct ps3vram_priv *priv, u32 data) +{ + *(priv->fifo_ptr)++ = data; +} + +static void ps3vram_begin_ring(struct ps3vram_priv *priv, u32 chan, u32 tag, + u32 size) +{ + ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag); +} + +static void ps3vram_rewind_ring(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + int status; + + ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET)); + + priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; + + /* asking the HV for a blit will kick the FIFO */ + status = lv1_gpu_context_attribute(priv->context_handle, + L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, 0, + 0, 0, 0); + if (status) + dev_err(&dev->core, + "%s: lv1_gpu_context_attribute failed %d\n", __func__, + status); + + priv->fifo_ptr = priv->fifo_base; +} + +static void ps3vram_fire_ring(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + int status; + + mutex_lock(&ps3_gpu_mutex); + + priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET + + (priv->fifo_ptr - priv->fifo_base) * sizeof(u32); + + /* asking the HV for a blit will kick the FIFO */ + status = lv1_gpu_context_attribute(priv->context_handle, + L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, 0, + 0, 0, 0); + if (status) + dev_err(&dev->core, + "%s: lv1_gpu_context_attribute failed %d\n", __func__, + status); + + if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) > + FIFO_SIZE - 1024) { + dev_dbg(&dev->core, "FIFO full, rewinding\n"); + ps3vram_wait_ring(dev, 200); + ps3vram_rewind_ring(dev); + } + + mutex_unlock(&ps3_gpu_mutex); +} + +static void ps3vram_bind(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0, 1); + ps3vram_out_ring(priv, 0x31337303); + ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x180, 3); + ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); + ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ + ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ + + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0, 1); + ps3vram_out_ring(priv, 0x3137c0de); + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x180, 3); + ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); + ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ + ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ + + ps3vram_fire_ring(dev); +} + +static int ps3vram_upload(struct ps3_system_bus_device *dev, + unsigned int src_offset, unsigned int dst_offset, + int len, int count) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_begin_ring(priv, UPLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + ps3vram_out_ring(priv, XDR_IOIF + src_offset); + ps3vram_out_ring(priv, dst_offset); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, count); + ps3vram_out_ring(priv, (1 << 8) | 1); + ps3vram_out_ring(priv, 0); + + ps3vram_notifier_reset(dev); + ps3vram_begin_ring(priv, UPLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); + ps3vram_out_ring(priv, 0); + ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x100, 1); + ps3vram_out_ring(priv, 0); + ps3vram_fire_ring(dev); + if (ps3vram_notifier_wait(dev, 200) < 0) { + dev_warn(&dev->core, "%s: Notifier timeout\n", __func__); + return -1; + } + + return 0; +} + +static int ps3vram_download(struct ps3_system_bus_device *dev, + unsigned int src_offset, unsigned int dst_offset, + int len, int count) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + ps3vram_out_ring(priv, src_offset); + ps3vram_out_ring(priv, XDR_IOIF + dst_offset); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, count); + ps3vram_out_ring(priv, (1 << 8) | 1); + ps3vram_out_ring(priv, 0); + + ps3vram_notifier_reset(dev); + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); + ps3vram_out_ring(priv, 0); + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x100, 1); + ps3vram_out_ring(priv, 0); + ps3vram_fire_ring(dev); + if (ps3vram_notifier_wait(dev, 200) < 0) { + dev_warn(&dev->core, "%s: Notifier timeout\n", __func__); + return -1; + } + + return 0; +} + +static void ps3vram_cache_evict(struct ps3_system_bus_device *dev, int entry) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + + if (!(cache->tags[entry].flags & CACHE_PAGE_DIRTY)) + return; + + dev_dbg(&dev->core, "Flushing %d: 0x%08x\n", entry, + cache->tags[entry].address); + if (ps3vram_upload(dev, CACHE_OFFSET + entry * cache->page_size, + cache->tags[entry].address, DMA_PAGE_SIZE, + cache->page_size / DMA_PAGE_SIZE) < 0) { + dev_err(&dev->core, + "Failed to upload from 0x%x to " "0x%x size 0x%x\n", + entry * cache->page_size, cache->tags[entry].address, + cache->page_size); + } + cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY; +} + +static void ps3vram_cache_load(struct ps3_system_bus_device *dev, int entry, + unsigned int address) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + + dev_dbg(&dev->core, "Fetching %d: 0x%08x\n", entry, address); + if (ps3vram_download(dev, address, + CACHE_OFFSET + entry * cache->page_size, + DMA_PAGE_SIZE, + cache->page_size / DMA_PAGE_SIZE) < 0) { + dev_err(&dev->core, + "Failed to download from 0x%x to 0x%x size 0x%x\n", + address, entry * cache->page_size, cache->page_size); + } + + cache->tags[entry].address = address; + cache->tags[entry].flags |= CACHE_PAGE_PRESENT; +} + + +static void ps3vram_cache_flush(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + int i; + + dev_dbg(&dev->core, "FLUSH\n"); + for (i = 0; i < cache->page_count; i++) { + ps3vram_cache_evict(dev, i); + cache->tags[i].flags = 0; + } +} + +static unsigned int ps3vram_cache_match(struct ps3_system_bus_device *dev, + loff_t address) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + unsigned int base; + unsigned int offset; + int i; + static int counter; + + offset = (unsigned int) (address & (cache->page_size - 1)); + base = (unsigned int) (address - offset); + + /* fully associative check */ + for (i = 0; i < cache->page_count; i++) { + if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) && + cache->tags[i].address == base) { + cache->hit++; + dev_dbg(&dev->core, "Found entry %d: 0x%08x\n", i, + cache->tags[i].address); + return i; + } + } + + /* choose a random entry */ + i = (jiffies + (counter++)) % cache->page_count; + dev_dbg(&dev->core, "Using entry %d\n", i); + + ps3vram_cache_evict(dev, i); + ps3vram_cache_load(dev, i, base); + + cache->miss++; + return i; +} + +static int ps3vram_cache_init(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + priv->cache.page_count = CACHE_PAGE_COUNT; + priv->cache.page_size = CACHE_PAGE_SIZE; + priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) * + CACHE_PAGE_COUNT, GFP_KERNEL); + if (priv->cache.tags == NULL) { + dev_err(&dev->core, "Could not allocate cache tags\n"); + return -ENOMEM; + } + + dev_info(&dev->core, "Created ram cache: %d entries, %d KiB each\n", + CACHE_PAGE_COUNT, CACHE_PAGE_SIZE / 1024); + + return 0; +} + +static void ps3vram_cache_cleanup(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_cache_flush(dev); + kfree(priv->cache.tags); +} + +static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from, + size_t len, size_t *retlen, u_char *buf) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + unsigned int cached, count; + + dev_dbg(&dev->core, "%s: from=0x%08x len=0x%zx\n", __func__, + (unsigned int)from, len); + + if (from >= priv->size) + return -EIO; + + if (len > priv->size - from) + len = priv->size - from; + + /* Copy from vram to buf */ + count = len; + while (count) { + unsigned int offset, avail; + unsigned int entry; + + offset = (unsigned int) (from & (priv->cache.page_size - 1)); + avail = priv->cache.page_size - offset; + + mutex_lock(&priv->lock); + + entry = ps3vram_cache_match(dev, from); + cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; + + dev_dbg(&dev->core, "%s: from=%08x cached=%08x offset=%08x " + "avail=%08x count=%08x\n", __func__, + (unsigned int)from, cached, offset, avail, count); + + if (avail > count) + avail = count; + memcpy(buf, priv->xdr_buf + cached, avail); + + mutex_unlock(&priv->lock); + + buf += avail; + count -= avail; + from += avail; + } + + *retlen = len; + return 0; +} + +static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to, + size_t len, size_t *retlen, const u_char *buf) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + unsigned int cached, count; + + if (to >= priv->size) + return -EIO; + + if (len > priv->size - to) + len = priv->size - to; + + /* Copy from buf to vram */ + count = len; + while (count) { + unsigned int offset, avail; + unsigned int entry; + + offset = (unsigned int) (to & (priv->cache.page_size - 1)); + avail = priv->cache.page_size - offset; + + mutex_lock(&priv->lock); + + entry = ps3vram_cache_match(dev, to); + cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; + + dev_dbg(&dev->core, "%s: to=%08x cached=%08x offset=%08x " + "avail=%08x count=%08x\n", __func__, (unsigned int)to, + cached, offset, avail, count); + + if (avail > count) + avail = count; + memcpy(priv->xdr_buf + cached, buf, avail); + + priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY; + + mutex_unlock(&priv->lock); + + buf += avail; + count -= avail; + to += avail; + } + + *retlen = len; + return 0; +} + +static int ps3vram_proc_show(struct seq_file *m, void *v) +{ + struct ps3vram_priv *priv = m->private; + + seq_printf(m, "hit:%u\nmiss:%u\n", priv->cache.hit, priv->cache.miss); + return 0; +} + +static int ps3vram_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, ps3vram_proc_show, PDE(inode)->data); +} + +static const struct file_operations ps3vram_proc_fops = { + .owner = THIS_MODULE, + .open = ps3vram_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct proc_dir_entry *pde; + + pde = proc_create(DEVICE_NAME, 0444, NULL, &ps3vram_proc_fops); + if (!pde) { + dev_warn(&dev->core, "failed to create /proc entry\n"); + return; + } + + pde->owner = THIS_MODULE; + pde->data = priv; +} + +static int ps3vram_make_request(struct request_queue *q, struct bio *bio) +{ + struct ps3_system_bus_device *dev = q->queuedata; + int write = bio_data_dir(bio) == WRITE; + const char *op = write ? "write" : "read"; + loff_t offset = bio->bi_sector << 9; + int error = 0; + struct bio_vec *bvec; + unsigned int i; + + dev_dbg(&dev->core, "%s\n", __func__); + + bio_for_each_segment(bvec, bio, i) { + /* PS3 is ppc64, so we don't handle highmem */ + char *ptr = page_address(bvec->bv_page) + bvec->bv_offset; + size_t len = bvec->bv_len, retlen; + + dev_dbg(&dev->core, " %s %zu bytes at offset %llu\n", op, + len, offset); + if (write) + error = ps3vram_write(dev, offset, len, &retlen, ptr); + else + error = ps3vram_read(dev, offset, len, &retlen, ptr); + + if (error) { + dev_err(&dev->core, "%s failed\n", op); + goto out; + } + + if (retlen != len) { + dev_err(&dev->core, "Short %s\n", op); + goto out; + } + + offset += len; + } + + dev_dbg(&dev->core, "%s completed\n", op); + +out: + bio_endio(bio, error); + return 0; +} + +static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv; + int error, status; + struct request_queue *queue; + struct gendisk *gendisk; + u64 ddr_lpar, ctrl_lpar, info_lpar, reports_lpar, ddr_size, + reports_size; + char *rest; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + error = -ENOMEM; + goto fail; + } + + mutex_init(&priv->lock); + dev->core.driver_data = priv; + + priv = dev->core.driver_data; + + /* Allocate XDR buffer (1MiB aligned) */ + priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL, + get_order(XDR_BUF_SIZE)); + if (priv->xdr_buf == NULL) { + dev_err(&dev->core, "Could not allocate XDR buffer\n"); + error = -ENOMEM; + goto fail_free_priv; + } + + /* Put FIFO at begginning of XDR buffer */ + priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET); + priv->fifo_ptr = priv->fifo_base; + + /* XXX: Need to open GPU, in case ps3fb or snd_ps3 aren't loaded */ + if (ps3_open_hv_device(dev)) { + dev_err(&dev->core, "ps3_open_hv_device failed\n"); + error = -EAGAIN; + goto out_close_gpu; + } + + /* Request memory */ + status = -1; + ddr_size = ALIGN(memparse(size, &rest), 1024*1024); + if (!ddr_size) { + dev_err(&dev->core, "Specified size is too small\n"); + error = -EINVAL; + goto out_close_gpu; + } + + while (ddr_size > 0) { + status = lv1_gpu_memory_allocate(ddr_size, 0, 0, 0, 0, + &priv->memory_handle, + &ddr_lpar); + if (!status) + break; + ddr_size -= 1024*1024; + } + if (status) { + dev_err(&dev->core, "lv1_gpu_memory_allocate failed %d\n", + status); + error = -ENOMEM; + goto out_free_xdr_buf; + } + + /* Request context */ + status = lv1_gpu_context_allocate(priv->memory_handle, 0, + &priv->context_handle, &ctrl_lpar, + &info_lpar, &reports_lpar, + &reports_size); + if (status) { + dev_err(&dev->core, "lv1_gpu_context_allocate failed %d\n", + status); + error = -ENOMEM; + goto out_free_memory; + } + + /* Map XDR buffer to RSX */ + status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, + ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)), + XDR_BUF_SIZE, 0); + if (status) { + dev_err(&dev->core, "lv1_gpu_context_iomap failed %d\n", + status); + error = -ENOMEM; + goto out_free_context; + } + + priv->ddr_base = ioremap_flags(ddr_lpar, ddr_size, _PAGE_NO_CACHE); + + if (!priv->ddr_base) { + dev_err(&dev->core, "ioremap DDR failed\n"); + error = -ENOMEM; + goto out_free_context; + } + + priv->ctrl = ioremap(ctrl_lpar, 64 * 1024); + if (!priv->ctrl) { + dev_err(&dev->core, "ioremap CTRL failed\n"); + error = -ENOMEM; + goto out_unmap_vram; + } + + priv->reports = ioremap(reports_lpar, reports_size); + if (!priv->reports) { + dev_err(&dev->core, "ioremap REPORTS failed\n"); + error = -ENOMEM; + goto out_unmap_ctrl; + } + + mutex_lock(&ps3_gpu_mutex); + ps3vram_init_ring(dev); + mutex_unlock(&ps3_gpu_mutex); + + priv->size = ddr_size; + + ps3vram_bind(dev); + + mutex_lock(&ps3_gpu_mutex); + error = ps3vram_wait_ring(dev, 100); + mutex_unlock(&ps3_gpu_mutex); + if (error < 0) { + dev_err(&dev->core, "Failed to initialize channels\n"); + error = -ETIMEDOUT; + goto out_unmap_reports; + } + + ps3vram_cache_init(dev); + ps3vram_proc_init(dev); + + queue = blk_alloc_queue(GFP_KERNEL); + if (!queue) { + dev_err(&dev->core, "blk_alloc_queue failed\n"); + error = -ENOMEM; + goto out_cache_cleanup; + } + + priv->queue = queue; + queue->queuedata = dev; + blk_queue_make_request(queue, ps3vram_make_request); + blk_queue_max_phys_segments(queue, MAX_PHYS_SEGMENTS); + blk_queue_max_hw_segments(queue, MAX_HW_SEGMENTS); + blk_queue_max_segment_size(queue, MAX_SEGMENT_SIZE); + blk_queue_max_sectors(queue, SAFE_MAX_SECTORS); + + gendisk = alloc_disk(1); + if (!gendisk) { + dev_err(&dev->core, "alloc_disk failed\n"); + error = -ENOMEM; + goto fail_cleanup_queue; + } + + priv->gendisk = gendisk; + gendisk->major = ps3vram_major; + gendisk->first_minor = 0; + gendisk->fops = &ps3vram_fops; + gendisk->queue = queue; + gendisk->private_data = dev; + gendisk->driverfs_dev = &dev->core; + strlcpy(gendisk->disk_name, DEVICE_NAME, sizeof(gendisk->disk_name)); + set_capacity(gendisk, priv->size >> 9); + + dev_info(&dev->core, "%s: Using %lu MiB of GPU memory\n", + gendisk->disk_name, get_capacity(gendisk) >> 11); + + add_disk(gendisk); + return 0; + +fail_cleanup_queue: + blk_cleanup_queue(queue); +out_cache_cleanup: + remove_proc_entry(DEVICE_NAME, NULL); + ps3vram_cache_cleanup(dev); +out_unmap_reports: + iounmap(priv->reports); +out_unmap_ctrl: + iounmap(priv->ctrl); +out_unmap_vram: + iounmap(priv->ddr_base); +out_free_context: + lv1_gpu_context_free(priv->context_handle); +out_free_memory: + lv1_gpu_memory_free(priv->memory_handle); +out_close_gpu: + ps3_close_hv_device(dev); +out_free_xdr_buf: + free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); +fail_free_priv: + kfree(priv); + dev->core.driver_data = NULL; +fail: + return error; +} + +static int ps3vram_remove(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + del_gendisk(priv->gendisk); + put_disk(priv->gendisk); + blk_cleanup_queue(priv->queue); + remove_proc_entry(DEVICE_NAME, NULL); + ps3vram_cache_cleanup(dev); + iounmap(priv->reports); + iounmap(priv->ctrl); + iounmap(priv->ddr_base); + lv1_gpu_context_free(priv->context_handle); + lv1_gpu_memory_free(priv->memory_handle); + ps3_close_hv_device(dev); + free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); + kfree(priv); + dev->core.driver_data = NULL; + return 0; +} + +static struct ps3_system_bus_driver ps3vram = { + .match_id = PS3_MATCH_ID_GPU, + .match_sub_id = PS3_MATCH_SUB_ID_GPU_RAMDISK, + .core.name = DEVICE_NAME, + .core.owner = THIS_MODULE, + .probe = ps3vram_probe, + .remove = ps3vram_remove, + .shutdown = ps3vram_remove, +}; + + +static int __init ps3vram_init(void) +{ + int error; + + if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) + return -ENODEV; + + error = register_blkdev(0, DEVICE_NAME); + if (error <= 0) { + pr_err("%s: register_blkdev failed %d\n", DEVICE_NAME, error); + return error; + } + ps3vram_major = error; + + pr_info("%s: registered block device major %d\n", DEVICE_NAME, + ps3vram_major); + + error = ps3_system_bus_driver_register(&ps3vram); + if (error) + unregister_blkdev(ps3vram_major, DEVICE_NAME); + + return error; +} + +static void __exit ps3vram_exit(void) +{ + ps3_system_bus_driver_unregister(&ps3vram); + unregister_blkdev(ps3vram_major, DEVICE_NAME); +} + +module_init(ps3vram_init); +module_exit(ps3vram_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("PS3 Video RAM Storage Driver"); +MODULE_AUTHOR("Sony Corporation"); +MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_RAMDISK); diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index bc33200535fc..6fde0a2e3567 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -120,13 +120,6 @@ config MTD_PHRAM doesn't have access to, memory beyond the mem=xxx limit, nvram, memory on the video card, etc... -config MTD_PS3VRAM - tristate "PS3 video RAM" - depends on FB_PS3 - help - This driver allows you to use excess PS3 video RAM as volatile - storage or system swap. - config MTD_LART tristate "28F160xx flash driver for LART" depends on SA1100_LART diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index e51521df4e40..0993d5cf3923 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -16,4 +16,3 @@ obj-$(CONFIG_MTD_LART) += lart.o obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o obj-$(CONFIG_MTD_M25P80) += m25p80.o -obj-$(CONFIG_MTD_PS3VRAM) += ps3vram.o diff --git a/drivers/mtd/devices/ps3vram.c b/drivers/mtd/devices/ps3vram.c deleted file mode 100644 index d21e9beb7ed2..000000000000 --- a/drivers/mtd/devices/ps3vram.c +++ /dev/null @@ -1,768 +0,0 @@ -/** - * ps3vram - Use extra PS3 video ram as MTD block device. - * - * Copyright (c) 2007-2008 Jim Paris - * Added support RSX DMA Vivien Chappelier - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define DEVICE_NAME "ps3vram" - -#define XDR_BUF_SIZE (2 * 1024 * 1024) /* XDR buffer (must be 1MiB aligned) */ -#define XDR_IOIF 0x0c000000 - -#define FIFO_BASE XDR_IOIF -#define FIFO_SIZE (64 * 1024) - -#define DMA_PAGE_SIZE (4 * 1024) - -#define CACHE_PAGE_SIZE (256 * 1024) -#define CACHE_PAGE_COUNT ((XDR_BUF_SIZE - FIFO_SIZE) / CACHE_PAGE_SIZE) - -#define CACHE_OFFSET CACHE_PAGE_SIZE -#define FIFO_OFFSET 0 - -#define CTRL_PUT 0x10 -#define CTRL_GET 0x11 -#define CTRL_TOP 0x15 - -#define UPLOAD_SUBCH 1 -#define DOWNLOAD_SUBCH 2 - -#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c -#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104 - -#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601 - -struct mtd_info ps3vram_mtd; - -#define CACHE_PAGE_PRESENT 1 -#define CACHE_PAGE_DIRTY 2 - -struct ps3vram_tag { - unsigned int address; - unsigned int flags; -}; - -struct ps3vram_cache { - unsigned int page_count; - unsigned int page_size; - struct ps3vram_tag *tags; -}; - -struct ps3vram_priv { - u64 memory_handle; - u64 context_handle; - u32 *ctrl; - u32 *reports; - u8 __iomem *ddr_base; - u8 *xdr_buf; - - u32 *fifo_base; - u32 *fifo_ptr; - - struct device *dev; - struct ps3vram_cache cache; - - /* Used to serialize cache/DMA operations */ - struct mutex lock; -}; - -#define DMA_NOTIFIER_HANDLE_BASE 0x66604200 /* first DMA notifier handle */ -#define DMA_NOTIFIER_OFFSET_BASE 0x1000 /* first DMA notifier offset */ -#define DMA_NOTIFIER_SIZE 0x40 -#define NOTIFIER 7 /* notifier used for completion report */ - -/* A trailing '-' means to subtract off ps3fb_videomemory.size */ -char *size = "256M-"; -module_param(size, charp, 0); -MODULE_PARM_DESC(size, "memory size"); - -static u32 *ps3vram_get_notifier(u32 *reports, int notifier) -{ - return (void *) reports + - DMA_NOTIFIER_OFFSET_BASE + - DMA_NOTIFIER_SIZE * notifier; -} - -static void ps3vram_notifier_reset(struct mtd_info *mtd) -{ - int i; - - struct ps3vram_priv *priv = mtd->priv; - u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); - for (i = 0; i < 4; i++) - notify[i] = 0xffffffff; -} - -static int ps3vram_notifier_wait(struct mtd_info *mtd, unsigned int timeout_ms) -{ - struct ps3vram_priv *priv = mtd->priv; - u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); - unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); - - do { - if (!notify[3]) - return 0; - msleep(1); - } while (time_before(jiffies, timeout)); - - return -ETIMEDOUT; -} - -static void ps3vram_init_ring(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; - priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET; -} - -static int ps3vram_wait_ring(struct mtd_info *mtd, unsigned int timeout_ms) -{ - struct ps3vram_priv *priv = mtd->priv; - unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); - - do { - if (priv->ctrl[CTRL_PUT] == priv->ctrl[CTRL_GET]) - return 0; - msleep(1); - } while (time_before(jiffies, timeout)); - - dev_dbg(priv->dev, "%s:%d: FIFO timeout (%08x/%08x/%08x)\n", __func__, - __LINE__, priv->ctrl[CTRL_PUT], priv->ctrl[CTRL_GET], - priv->ctrl[CTRL_TOP]); - - return -ETIMEDOUT; -} - -static void ps3vram_out_ring(struct ps3vram_priv *priv, u32 data) -{ - *(priv->fifo_ptr)++ = data; -} - -static void ps3vram_begin_ring(struct ps3vram_priv *priv, u32 chan, - u32 tag, u32 size) -{ - ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag); -} - -static void ps3vram_rewind_ring(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - u64 status; - - ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET)); - - priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; - - /* asking the HV for a blit will kick the fifo */ - status = lv1_gpu_context_attribute(priv->context_handle, - L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, - 0, 0, 0, 0); - if (status) - dev_err(priv->dev, "%s:%d: lv1_gpu_context_attribute failed\n", - __func__, __LINE__); - - priv->fifo_ptr = priv->fifo_base; -} - -static void ps3vram_fire_ring(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - u64 status; - - mutex_lock(&ps3_gpu_mutex); - - priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET + - (priv->fifo_ptr - priv->fifo_base) * sizeof(u32); - - /* asking the HV for a blit will kick the fifo */ - status = lv1_gpu_context_attribute(priv->context_handle, - L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, - 0, 0, 0, 0); - if (status) - dev_err(priv->dev, "%s:%d: lv1_gpu_context_attribute failed\n", - __func__, __LINE__); - - if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) > - FIFO_SIZE - 1024) { - dev_dbg(priv->dev, "%s:%d: fifo full, rewinding\n", __func__, - __LINE__); - ps3vram_wait_ring(mtd, 200); - ps3vram_rewind_ring(mtd); - } - - mutex_unlock(&ps3_gpu_mutex); -} - -static void ps3vram_bind(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0, 1); - ps3vram_out_ring(priv, 0x31337303); - ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x180, 3); - ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); - ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ - ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ - - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0, 1); - ps3vram_out_ring(priv, 0x3137c0de); - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x180, 3); - ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); - ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ - ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ - - ps3vram_fire_ring(mtd); -} - -static int ps3vram_upload(struct mtd_info *mtd, unsigned int src_offset, - unsigned int dst_offset, int len, int count) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_begin_ring(priv, UPLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); - ps3vram_out_ring(priv, XDR_IOIF + src_offset); - ps3vram_out_ring(priv, dst_offset); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, count); - ps3vram_out_ring(priv, (1 << 8) | 1); - ps3vram_out_ring(priv, 0); - - ps3vram_notifier_reset(mtd); - ps3vram_begin_ring(priv, UPLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); - ps3vram_out_ring(priv, 0); - ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x100, 1); - ps3vram_out_ring(priv, 0); - ps3vram_fire_ring(mtd); - if (ps3vram_notifier_wait(mtd, 200) < 0) { - dev_dbg(priv->dev, "%s:%d: notifier timeout\n", __func__, - __LINE__); - return -1; - } - - return 0; -} - -static int ps3vram_download(struct mtd_info *mtd, unsigned int src_offset, - unsigned int dst_offset, int len, int count) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); - ps3vram_out_ring(priv, src_offset); - ps3vram_out_ring(priv, XDR_IOIF + dst_offset); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, count); - ps3vram_out_ring(priv, (1 << 8) | 1); - ps3vram_out_ring(priv, 0); - - ps3vram_notifier_reset(mtd); - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); - ps3vram_out_ring(priv, 0); - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x100, 1); - ps3vram_out_ring(priv, 0); - ps3vram_fire_ring(mtd); - if (ps3vram_notifier_wait(mtd, 200) < 0) { - dev_dbg(priv->dev, "%s:%d: notifier timeout\n", __func__, - __LINE__); - return -1; - } - - return 0; -} - -static void ps3vram_cache_evict(struct mtd_info *mtd, int entry) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - - if (cache->tags[entry].flags & CACHE_PAGE_DIRTY) { - dev_dbg(priv->dev, "%s:%d: flushing %d : 0x%08x\n", __func__, - __LINE__, entry, cache->tags[entry].address); - if (ps3vram_upload(mtd, - CACHE_OFFSET + entry * cache->page_size, - cache->tags[entry].address, - DMA_PAGE_SIZE, - cache->page_size / DMA_PAGE_SIZE) < 0) { - dev_dbg(priv->dev, "%s:%d: failed to upload from " - "0x%x to 0x%x size 0x%x\n", __func__, __LINE__, - entry * cache->page_size, - cache->tags[entry].address, cache->page_size); - } - cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY; - } -} - -static void ps3vram_cache_load(struct mtd_info *mtd, int entry, - unsigned int address) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - - dev_dbg(priv->dev, "%s:%d: fetching %d : 0x%08x\n", __func__, __LINE__, - entry, address); - if (ps3vram_download(mtd, - address, - CACHE_OFFSET + entry * cache->page_size, - DMA_PAGE_SIZE, - cache->page_size / DMA_PAGE_SIZE) < 0) { - dev_err(priv->dev, "%s:%d: failed to download from " - "0x%x to 0x%x size 0x%x\n", __func__, __LINE__, address, - entry * cache->page_size, cache->page_size); - } - - cache->tags[entry].address = address; - cache->tags[entry].flags |= CACHE_PAGE_PRESENT; -} - - -static void ps3vram_cache_flush(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - int i; - - dev_dbg(priv->dev, "%s:%d: FLUSH\n", __func__, __LINE__); - for (i = 0; i < cache->page_count; i++) { - ps3vram_cache_evict(mtd, i); - cache->tags[i].flags = 0; - } -} - -static unsigned int ps3vram_cache_match(struct mtd_info *mtd, loff_t address) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - unsigned int base; - unsigned int offset; - int i; - static int counter; - - offset = (unsigned int) (address & (cache->page_size - 1)); - base = (unsigned int) (address - offset); - - /* fully associative check */ - for (i = 0; i < cache->page_count; i++) { - if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) && - cache->tags[i].address == base) { - dev_dbg(priv->dev, "%s:%d: found entry %d : 0x%08x\n", - __func__, __LINE__, i, cache->tags[i].address); - return i; - } - } - - /* choose a random entry */ - i = (jiffies + (counter++)) % cache->page_count; - dev_dbg(priv->dev, "%s:%d: using entry %d\n", __func__, __LINE__, i); - - ps3vram_cache_evict(mtd, i); - ps3vram_cache_load(mtd, i, base); - - return i; -} - -static int ps3vram_cache_init(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - priv->cache.page_count = CACHE_PAGE_COUNT; - priv->cache.page_size = CACHE_PAGE_SIZE; - priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) * - CACHE_PAGE_COUNT, GFP_KERNEL); - if (priv->cache.tags == NULL) { - dev_err(priv->dev, "%s:%d: could not allocate cache tags\n", - __func__, __LINE__); - return -ENOMEM; - } - - dev_info(priv->dev, "created ram cache: %d entries, %d KiB each\n", - CACHE_PAGE_COUNT, CACHE_PAGE_SIZE / 1024); - - return 0; -} - -static void ps3vram_cache_cleanup(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_cache_flush(mtd); - kfree(priv->cache.tags); -} - -static int ps3vram_erase(struct mtd_info *mtd, struct erase_info *instr) -{ - struct ps3vram_priv *priv = mtd->priv; - - if (instr->addr + instr->len > mtd->size) - return -EINVAL; - - mutex_lock(&priv->lock); - - ps3vram_cache_flush(mtd); - - /* Set bytes to 0xFF */ - memset_io(priv->ddr_base + instr->addr, 0xFF, instr->len); - - mutex_unlock(&priv->lock); - - instr->state = MTD_ERASE_DONE; - mtd_erase_callback(instr); - - return 0; -} - -static int ps3vram_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - struct ps3vram_priv *priv = mtd->priv; - unsigned int cached, count; - - dev_dbg(priv->dev, "%s:%d: from=0x%08x len=0x%zx\n", __func__, __LINE__, - (unsigned int)from, len); - - if (from >= mtd->size) - return -EINVAL; - - if (len > mtd->size - from) - len = mtd->size - from; - - /* Copy from vram to buf */ - count = len; - while (count) { - unsigned int offset, avail; - unsigned int entry; - - offset = (unsigned int) (from & (priv->cache.page_size - 1)); - avail = priv->cache.page_size - offset; - - mutex_lock(&priv->lock); - - entry = ps3vram_cache_match(mtd, from); - cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; - - dev_dbg(priv->dev, "%s:%d: from=%08x cached=%08x offset=%08x " - "avail=%08x count=%08x\n", __func__, __LINE__, - (unsigned int)from, cached, offset, avail, count); - - if (avail > count) - avail = count; - memcpy(buf, priv->xdr_buf + cached, avail); - - mutex_unlock(&priv->lock); - - buf += avail; - count -= avail; - from += avail; - } - - *retlen = len; - return 0; -} - -static int ps3vram_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - struct ps3vram_priv *priv = mtd->priv; - unsigned int cached, count; - - if (to >= mtd->size) - return -EINVAL; - - if (len > mtd->size - to) - len = mtd->size - to; - - /* Copy from buf to vram */ - count = len; - while (count) { - unsigned int offset, avail; - unsigned int entry; - - offset = (unsigned int) (to & (priv->cache.page_size - 1)); - avail = priv->cache.page_size - offset; - - mutex_lock(&priv->lock); - - entry = ps3vram_cache_match(mtd, to); - cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; - - dev_dbg(priv->dev, "%s:%d: to=%08x cached=%08x offset=%08x " - "avail=%08x count=%08x\n", __func__, __LINE__, - (unsigned int)to, cached, offset, avail, count); - - if (avail > count) - avail = count; - memcpy(priv->xdr_buf + cached, buf, avail); - - priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY; - - mutex_unlock(&priv->lock); - - buf += avail; - count -= avail; - to += avail; - } - - *retlen = len; - return 0; -} - -static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev) -{ - struct ps3vram_priv *priv; - int status; - u64 ddr_lpar; - u64 ctrl_lpar; - u64 info_lpar; - u64 reports_lpar; - u64 ddr_size; - u64 reports_size; - int ret = -ENOMEM; - char *rest; - - ret = -EIO; - ps3vram_mtd.priv = kzalloc(sizeof(struct ps3vram_priv), GFP_KERNEL); - if (!ps3vram_mtd.priv) - goto out; - priv = ps3vram_mtd.priv; - - mutex_init(&priv->lock); - priv->dev = &dev->core; - - /* Allocate XDR buffer (1MiB aligned) */ - priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL, - get_order(XDR_BUF_SIZE)); - if (priv->xdr_buf == NULL) { - dev_dbg(&dev->core, "%s:%d: could not allocate XDR buffer\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_priv; - } - - /* Put FIFO at begginning of XDR buffer */ - priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET); - priv->fifo_ptr = priv->fifo_base; - - /* XXX: Need to open GPU, in case ps3fb or snd_ps3 aren't loaded */ - if (ps3_open_hv_device(dev)) { - dev_err(&dev->core, "%s:%d: ps3_open_hv_device failed\n", - __func__, __LINE__); - ret = -EAGAIN; - goto out_close_gpu; - } - - /* Request memory */ - status = -1; - ddr_size = memparse(size, &rest); - if (*rest == '-') - ddr_size -= ps3fb_videomemory.size; - ddr_size = ALIGN(ddr_size, 1024*1024); - if (ddr_size <= 0) { - dev_err(&dev->core, "%s:%d: specified size is too small\n", - __func__, __LINE__); - ret = -EINVAL; - goto out_close_gpu; - } - - while (ddr_size > 0) { - status = lv1_gpu_memory_allocate(ddr_size, 0, 0, 0, 0, - &priv->memory_handle, - &ddr_lpar); - if (!status) - break; - ddr_size -= 1024*1024; - } - if (status || ddr_size <= 0) { - dev_err(&dev->core, "%s:%d: lv1_gpu_memory_allocate failed\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_xdr_buf; - } - - /* Request context */ - status = lv1_gpu_context_allocate(priv->memory_handle, - 0, - &priv->context_handle, - &ctrl_lpar, - &info_lpar, - &reports_lpar, - &reports_size); - if (status) { - dev_err(&dev->core, "%s:%d: lv1_gpu_context_allocate failed\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_memory; - } - - /* Map XDR buffer to RSX */ - status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, - ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)), - XDR_BUF_SIZE, 0); - if (status) { - dev_err(&dev->core, "%s:%d: lv1_gpu_context_iomap failed\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_context; - } - - priv->ddr_base = ioremap_flags(ddr_lpar, ddr_size, _PAGE_NO_CACHE); - - if (!priv->ddr_base) { - dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, - __LINE__); - ret = -ENOMEM; - goto out_free_context; - } - - priv->ctrl = ioremap(ctrl_lpar, 64 * 1024); - if (!priv->ctrl) { - dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, - __LINE__); - ret = -ENOMEM; - goto out_unmap_vram; - } - - priv->reports = ioremap(reports_lpar, reports_size); - if (!priv->reports) { - dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, - __LINE__); - ret = -ENOMEM; - goto out_unmap_ctrl; - } - - mutex_lock(&ps3_gpu_mutex); - ps3vram_init_ring(&ps3vram_mtd); - mutex_unlock(&ps3_gpu_mutex); - - ps3vram_mtd.name = "ps3vram"; - ps3vram_mtd.size = ddr_size; - ps3vram_mtd.flags = MTD_CAP_RAM; - ps3vram_mtd.erase = ps3vram_erase; - ps3vram_mtd.point = NULL; - ps3vram_mtd.unpoint = NULL; - ps3vram_mtd.read = ps3vram_read; - ps3vram_mtd.write = ps3vram_write; - ps3vram_mtd.owner = THIS_MODULE; - ps3vram_mtd.type = MTD_RAM; - ps3vram_mtd.erasesize = CACHE_PAGE_SIZE; - ps3vram_mtd.writesize = 1; - - ps3vram_bind(&ps3vram_mtd); - - mutex_lock(&ps3_gpu_mutex); - ret = ps3vram_wait_ring(&ps3vram_mtd, 100); - mutex_unlock(&ps3_gpu_mutex); - if (ret < 0) { - dev_err(&dev->core, "%s:%d: failed to initialize channels\n", - __func__, __LINE__); - ret = -ETIMEDOUT; - goto out_unmap_reports; - } - - ps3vram_cache_init(&ps3vram_mtd); - - if (add_mtd_device(&ps3vram_mtd)) { - dev_err(&dev->core, "%s:%d: add_mtd_device failed\n", - __func__, __LINE__); - ret = -EAGAIN; - goto out_cache_cleanup; - } - - dev_info(&dev->core, "reserved %u MiB of gpu memory\n", - (unsigned int)(ddr_size / 1024 / 1024)); - - return 0; - -out_cache_cleanup: - ps3vram_cache_cleanup(&ps3vram_mtd); -out_unmap_reports: - iounmap(priv->reports); -out_unmap_ctrl: - iounmap(priv->ctrl); -out_unmap_vram: - iounmap(priv->ddr_base); -out_free_context: - lv1_gpu_context_free(priv->context_handle); -out_free_memory: - lv1_gpu_memory_free(priv->memory_handle); -out_close_gpu: - ps3_close_hv_device(dev); -out_free_xdr_buf: - free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); -out_free_priv: - kfree(ps3vram_mtd.priv); - ps3vram_mtd.priv = NULL; -out: - return ret; -} - -static int ps3vram_shutdown(struct ps3_system_bus_device *dev) -{ - struct ps3vram_priv *priv; - - priv = ps3vram_mtd.priv; - - del_mtd_device(&ps3vram_mtd); - ps3vram_cache_cleanup(&ps3vram_mtd); - iounmap(priv->reports); - iounmap(priv->ctrl); - iounmap(priv->ddr_base); - lv1_gpu_context_free(priv->context_handle); - lv1_gpu_memory_free(priv->memory_handle); - ps3_close_hv_device(dev); - free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); - kfree(priv); - return 0; -} - -static struct ps3_system_bus_driver ps3vram_driver = { - .match_id = PS3_MATCH_ID_GPU, - .match_sub_id = PS3_MATCH_SUB_ID_GPU_RAMDISK, - .core.name = DEVICE_NAME, - .core.owner = THIS_MODULE, - .probe = ps3vram_probe, - .remove = ps3vram_shutdown, - .shutdown = ps3vram_shutdown, -}; - -static int __init ps3vram_init(void) -{ - return ps3_system_bus_driver_register(&ps3vram_driver); -} - -static void __exit ps3vram_exit(void) -{ - ps3_system_bus_driver_unregister(&ps3vram_driver); -} - -module_init(ps3vram_init); -module_exit(ps3vram_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jim Paris "); -MODULE_DESCRIPTION("MTD driver for PS3 video RAM"); -MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_RAMDISK); -- cgit v1.2.3 From bfe4f4f800ccbb499a1120735016a20d3feacd4f Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 9 Jan 2009 18:57:06 -0600 Subject: parisc: remove klist iterators commit 11c3b5c3e08f4d855cbef52883c266b9ab9df879 Author: Greg Kroah-Hartman Date: Tue Dec 16 12:24:56 2008 -0800 driver core: move klist_children into private structure Broke our parisc build pretty badly because we touch the klists directly in three cases (AGP, SBA and GSC). Although GregKH will revert this patch, there's no reason we should be using the iterators directly, we can just move to the standard device_for_each_child() API. Signed-off-by: James Bottomley Tested-by: Helge Deller Tested-by: Kyle McMartin Signed-off-by: Kyle McMartin --- drivers/char/agp/parisc-agp.c | 23 ++++++++-------- drivers/parisc/gsc.c | 39 +++++++++++++++------------ drivers/parisc/sba_iommu.c | 61 +++++++++++++++++++++++++------------------ 3 files changed, 68 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index db60539bf67a..699e3422ad93 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c @@ -359,9 +359,16 @@ fail: return error; } -static struct device *next_device(struct klist_iter *i) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; +static int +find_quicksilver(struct device *dev, void *data) +{ + struct parisc_device **lba = data; + struct parisc_device *padev = to_parisc_device(dev); + + if (IS_QUICKSILVER(padev)) + *lba = padev; + + return 0; } static int @@ -372,8 +379,6 @@ parisc_agp_init(void) int err = -1; struct parisc_device *sba = NULL, *lba = NULL; struct lba_device *lbadev = NULL; - struct device *dev = NULL; - struct klist_iter i; if (!sba_list) goto out; @@ -386,13 +391,7 @@ parisc_agp_init(void) } /* Now search our Pluto for our precious AGP device... */ - klist_iter_init(&sba->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *padev = to_parisc_device(dev); - if (IS_QUICKSILVER(padev)) - lba = padev; - } - klist_iter_exit(&i); + device_for_each_child(&sba->dev, &lba, find_quicksilver); if (!lba) { printk(KERN_INFO DRVPFX "No AGP devices found.\n"); diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index e76db9e4d504..d33632917696 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c @@ -186,29 +186,34 @@ void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp) *irqp = irq; } -static struct device *next_device(struct klist_iter *i) +struct gsc_fixup_struct { + void (*choose_irq)(struct parisc_device *, void *); + void *ctrl; +}; + +static int gsc_fixup_irqs_callback(struct device *dev, void *data) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; + struct parisc_device *padev = to_parisc_device(dev); + struct gsc_fixup_struct *gf = data; + + /* work-around for 715/64 and others which have parent + at path [5] and children at path [5/0/x] */ + if (padev->id.hw_type == HPHW_FAULTY) + gsc_fixup_irqs(padev, gf->ctrl, gf->choose_irq); + gf->choose_irq(padev, gf->ctrl); + + return 0; } void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl, void (*choose_irq)(struct parisc_device *, void *)) { - struct device *dev; - struct klist_iter i; - - klist_iter_init(&parent->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *padev = to_parisc_device(dev); - - /* work-around for 715/64 and others which have parent - at path [5] and children at path [5/0/x] */ - if (padev->id.hw_type == HPHW_FAULTY) - return gsc_fixup_irqs(padev, ctrl, choose_irq); - choose_irq(padev, ctrl); - } - klist_iter_exit(&i); + struct gsc_fixup_struct data = { + .choose_irq = choose_irq, + .ctrl = ctrl, + }; + + device_for_each_child(&parent->dev, &data, gsc_fixup_irqs_callback); } int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic) diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index a70cf16ee1ad..6aad8546fd24 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1206,31 +1206,49 @@ sba_alloc_pdir(unsigned int pdir_size) return (void *) pdir_base; } -static struct device *next_device(struct klist_iter *i) +struct ibase_data_struct { + struct ioc *ioc; + int ioc_num; +}; + +static int setup_ibase_imask_callback(struct device *dev, void *data) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; + /* lba_set_iregs() is in drivers/parisc/lba_pci.c */ + extern void lba_set_iregs(struct parisc_device *, u32, u32); + struct parisc_device *lba = to_parisc_device(dev); + struct ibase_data_struct *ibd = data; + int rope_num = (lba->hpa.start >> 13) & 0xf; + if (rope_num >> 3 == ibd->ioc_num) + lba_set_iregs(lba, ibd->ioc->ibase, ibd->ioc->imask); + return 0; } /* setup Mercury or Elroy IBASE/IMASK registers. */ static void setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num) { - /* lba_set_iregs() is in drivers/parisc/lba_pci.c */ - extern void lba_set_iregs(struct parisc_device *, u32, u32); - struct device *dev; - struct klist_iter i; - - klist_iter_init(&sba->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *lba = to_parisc_device(dev); - int rope_num = (lba->hpa.start >> 13) & 0xf; - if (rope_num >> 3 == ioc_num) - lba_set_iregs(lba, ioc->ibase, ioc->imask); - } - klist_iter_exit(&i); + struct ibase_data_struct ibase_data = { + .ioc = ioc, + .ioc_num = ioc_num, + }; + + device_for_each_child(&sba->dev, &ibase_data, + setup_ibase_imask_callback); } +#ifdef SBA_AGP_SUPPORT +static int +sba_ioc_find_quicksilver(struct device *dev, void *data) +{ + int *agp_found = data; + struct parisc_device *lba = to_parisc_device(dev); + + if (IS_QUICKSILVER(lba)) + *agp_found = 1; + return 0; +} +#endif + static void sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) { @@ -1332,9 +1350,6 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) WRITE_REG(ioc->ibase | 31, ioc->ioc_hpa + IOC_PCOM); #ifdef SBA_AGP_SUPPORT -{ - struct klist_iter i; - struct device *dev = NULL; /* ** If an AGP device is present, only use half of the IOV space @@ -1344,13 +1359,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ** We program the next pdir index after we stop w/ a key for ** the GART code to handshake on. */ - klist_iter_init(&sba->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *lba = to_parisc_device(dev); - if (IS_QUICKSILVER(lba)) - agp_found = 1; - } - klist_iter_exit(&i); + device_for_each_child(&sba->dev, &agp_found, sba_ioc_find_quicksilver); if (agp_found && sba_reserve_agpgart) { printk(KERN_INFO "%s: reserving %dMb of IOVA space for agpgart\n", -- cgit v1.2.3 From 7f384ce780c6091968fc848b14f17b45cb849e14 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 13 Jan 2009 21:14:51 +0100 Subject: parisc: fix dev_printk() compile warnings for accessing a device struct Fix compile warnings: drivers/scsi/zalon.c: In function `zalon_probe': drivers/scsi/zalon.c:140: warning: passing arg 1 of `dev_driver_string' from incompatible pointer type drivers/scsi/zalon.c:140: warning: passing arg 1 of `dev_name' from incompatible pointer type Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- drivers/scsi/lasi700.c | 2 +- drivers/scsi/zalon.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index 4a4e6954ec79..f23c4ca9a2ee 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -103,7 +103,7 @@ lasi700_probe(struct parisc_device *dev) hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL); if (!hostdata) { - dev_printk(KERN_ERR, dev, "Failed to allocate host data\n"); + dev_printk(KERN_ERR, &dev->dev, "Failed to allocate host data\n"); return -ENOMEM; } diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index a8d61a62522e..97f3158fa7b5 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c @@ -137,7 +137,7 @@ zalon_probe(struct parisc_device *dev) goto fail; if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) { - dev_printk(KERN_ERR, dev, "irq problem with %d, detaching\n ", + dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ", dev->irq); goto fail; } -- cgit v1.2.3 From 9785d646c10b0707412516ffe56b71b9eb18861f Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Wed, 28 Jan 2009 22:30:55 -0700 Subject: parisc: fix wrong assumption about bus->self Kenji Kaneshige posted a patch series to linux-pci to fix a wrong assumption about pci_bus->self==NULL for all PCI host bus controllers. While PARISC platforms to not behave this way, I prefer to have the code consistent across architectures. The following patch replaces pci_bus->self with pci_bus->parent when used as a test to check for "root bus controller". Signed-off-by: Grant Grundler Signed-off-by: Kyle McMartin --- drivers/parisc/dino.c | 2 +- drivers/parisc/iosapic.c | 9 ++++----- drivers/parisc/lba_pci.c | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index d539d9df88e7..f79266cd00e5 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -587,7 +587,7 @@ dino_fixup_bus(struct pci_bus *bus) bus->resource[i+1] = &res[i]; } - } else if(bus->self) { + } else if (bus->parent) { int i; pci_read_bridge_bases(bus); diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 0797659ee016..1cdfdea5d7ef 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -487,7 +487,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) } /* Check if pcidev behind a PPB */ - if (NULL != pcidev->bus->self) { + if (pcidev->bus->parent) { /* Convert pcidev INTR_PIN into something we ** can lookup in the IRT. */ @@ -523,10 +523,9 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) #endif /* PCI_BRIDGE_FUNCS */ /* - ** Locate the host slot the PPB nearest the Host bus - ** adapter. - */ - while (NULL != p->parent->self) + * Locate the host slot of the PPB. + */ + while (p->parent->parent) p = p->parent; intr_slot = PCI_SLOT(p->self->devfn); diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index d8233de8c75d..59fbbf128365 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -644,7 +644,7 @@ lba_fixup_bus(struct pci_bus *bus) ** Properly Setup MMIO resources for this bus. ** pci_alloc_primary_bus() mangles this. */ - if (bus->self) { + if (bus->parent) { int i; /* PCI-PCI Bridge */ pci_read_bridge_bases(bus); @@ -802,7 +802,7 @@ lba_fixup_bus(struct pci_bus *bus) ** Can't fixup here anyway....garr... */ if (fbb_enable) { - if (bus->self) { + if (bus->parent) { u8 control; /* enable on PPB */ (void) pci_read_config_byte(bus->self, PCI_BRIDGE_CONTROL, &control); -- cgit v1.2.3 From 8b6649c575e0d8312f62fe643ae43558892da2e1 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 16 Feb 2009 03:20:54 -0500 Subject: parisc: convert cpu_check_affinity to new cpumask api cpumask arg to the affinity function is now const, sort that out through the irq_desc implementations. Signed-off-by: Kyle McMartin --- arch/parisc/include/asm/irq.h | 2 +- arch/parisc/kernel/irq.c | 12 +++++++----- drivers/parisc/iosapic.c | 7 +++++-- 3 files changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/arch/parisc/include/asm/irq.h b/arch/parisc/include/asm/irq.h index 399c81981ed5..dfa26b67f919 100644 --- a/arch/parisc/include/asm/irq.h +++ b/arch/parisc/include/asm/irq.h @@ -49,7 +49,7 @@ extern unsigned long txn_alloc_addr(unsigned int); extern unsigned long txn_affinity_addr(unsigned int irq, int cpu); extern int cpu_claim_irq(unsigned int irq, struct irq_chip *, void *); -extern int cpu_check_affinity(unsigned int irq, cpumask_t *dest); +extern int cpu_check_affinity(unsigned int irq, const struct cpumask *dest); /* soft power switch support (power.c) */ extern struct tasklet_struct power_tasklet; diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c index a572112f5aba..29e70e16ede8 100644 --- a/arch/parisc/kernel/irq.c +++ b/arch/parisc/kernel/irq.c @@ -112,7 +112,7 @@ void cpu_end_irq(unsigned int irq) } #ifdef CONFIG_SMP -int cpu_check_affinity(unsigned int irq, cpumask_t *dest) +int cpu_check_affinity(unsigned int irq, const struct cpumask *dest) { int cpu_dest; @@ -126,17 +126,19 @@ int cpu_check_affinity(unsigned int irq, cpumask_t *dest) /* whatever mask they set, we just allow one CPU */ cpu_dest = first_cpu(*dest); - *dest = cpumask_of_cpu(cpu_dest); - return 0; + return cpu_dest; } static void cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest) { - if (cpu_check_affinity(irq, dest)) + int cpu_dest; + + cpu_dest = cpu_check_affinity(irq, dest); + if (cpu_dest < 0) return; - cpumask_copy(&irq_desc[irq].affinity, dest); + cpumask_copy(&irq_desc[irq].affinity, &cpumask_of_cpu(cpu_dest)); } #endif diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 1cdfdea5d7ef..501aaf1f253f 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -708,11 +708,14 @@ static void iosapic_set_affinity_irq(unsigned int irq, struct vector_info *vi = iosapic_get_vector(irq); u32 d0, d1, dummy_d0; unsigned long flags; + int dest_cpu; - if (cpu_check_affinity(irq, dest)) + dest_cpu = cpu_check_affinity(irq, dest); + if (dest_cpu < 0) return; - vi->txn_addr = txn_affinity_addr(irq, cpumask_first(dest)); + irq_desc[irq].affinity = cpumask_of_cpu(dest_cpu); + vi->txn_addr = txn_affinity_addr(irq, dest_cpu); spin_lock_irqsave(&iosapic_lock, flags); /* d1 contains the destination CPU, so only want to set that -- cgit v1.2.3 From d4995244bd4c02eb7bea3c63aee81a2f2b64910e Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Mon, 26 Jan 2009 03:53:16 +0000 Subject: parisc: dino: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers Signed-off-by: Kyle McMartin --- drivers/parisc/dino.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index f79266cd00e5..bb5a1c9597cb 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -479,7 +479,7 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr) res = &dino_dev->hba.lmmio_space; res->flags = IORESOURCE_MEM; size = scnprintf(name, sizeof(name), "Dino LMMIO (%s)", - bus->bridge->bus_id); + dev_name(bus->bridge)); res->name = kmalloc(size+1, GFP_KERNEL); if(res->name) strcpy((char *)res->name, name); @@ -493,7 +493,7 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr) struct list_head *ln, *tmp_ln; printk(KERN_ERR "Dino: cannot attach bus %s\n", - bus->bridge->bus_id); + dev_name(bus->bridge)); /* kill the bus, we can't do anything with it */ list_for_each_safe(ln, tmp_ln, &bus->devices) { struct pci_dev *dev = pci_dev_b(ln); @@ -611,12 +611,12 @@ dino_fixup_bus(struct pci_bus *bus) } DBG("DEBUG %s assigning %d [0x%lx,0x%lx]\n", - bus->self->dev.bus_id, i, + dev_name(&bus->self->dev), i, bus->self->resource[i].start, bus->self->resource[i].end); pci_assign_resource(bus->self, i); DBG("DEBUG %s after assign %d [0x%lx,0x%lx]\n", - bus->self->dev.bus_id, i, + dev_name(&bus->self->dev), i, bus->self->resource[i].start, bus->self->resource[i].end); } @@ -1026,7 +1026,8 @@ static int __init dino_probe(struct parisc_device *dev) dino_current_bus = bus->subordinate + 1; pci_bus_assign_resources(bus); } else { - printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", dev->dev.bus_id, dino_current_bus); + printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", + dev_name(&dev->dev), dino_current_bus); /* increment the bus number in case of duplicates */ dino_current_bus++; } -- cgit v1.2.3 From d284e4f71dd42826fb60df33846ba310310c6c51 Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Mon, 26 Jan 2009 19:08:48 -0300 Subject: V4L/DVB (10974): Use Diseqc 3/3 mode to send data Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stb0899_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c index 10613acf18f5..a04c782fff8d 100644 --- a/drivers/media/dvb/frontends/stb0899_drv.c +++ b/drivers/media/dvb/frontends/stb0899_drv.c @@ -794,7 +794,7 @@ static int stb0899_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t reg = stb0899_read_reg(state, STB0899_DISCNTRL1); old_state = reg; /* set to burst mode */ - STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x02); + STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x03); STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x01); stb0899_write_reg(state, STB0899_DISCNTRL1, reg); switch (burst) { -- cgit v1.2.3 From b5d067b8e331ce78f4a81eb220965ffa36069d3f Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 27 Jan 2009 11:03:16 -0300 Subject: V4L/DVB (10975): Bug: Use signed types, Offsets and range can be negative Code simplification: use in kernel macros Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stb0899_algo.c | 14 +++++++------- drivers/media/dvb/frontends/stb0899_priv.h | 12 ++++-------- 2 files changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb/frontends/stb0899_algo.c index a67d1775a43c..2da55ec20392 100644 --- a/drivers/media/dvb/frontends/stb0899_algo.c +++ b/drivers/media/dvb/frontends/stb0899_algo.c @@ -156,7 +156,7 @@ static void stb0899_first_subrange(struct stb0899_state *state) } if (range > 0) - internal->sub_range = MIN(internal->srch_range, range); + internal->sub_range = min(internal->srch_range, range); else internal->sub_range = 0; @@ -185,7 +185,7 @@ static enum stb0899_status stb0899_check_tmg(struct stb0899_state *state) timing = stb0899_read_reg(state, STB0899_RTF); if (lock >= 42) { - if ((lock > 48) && (ABS(timing) >= 110)) { + if ((lock > 48) && (abs(timing) >= 110)) { internal->status = ANALOGCARRIER; dprintk(state->verbose, FE_DEBUG, 1, "-->ANALOG Carrier !"); } else { @@ -222,7 +222,7 @@ static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) index++; derot_freq += index * internal->direction * derot_step; /* next derot zig zag position */ - if (ABS(derot_freq) > derot_limit) + if (abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -298,7 +298,7 @@ static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state) last_derot_freq = derot_freq; derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */ - if(ABS(derot_freq) > derot_limit) + if(abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -400,7 +400,7 @@ static enum stb0899_status stb0899_search_data(struct stb0899_state *state) if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) { derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ - if (ABS(derot_freq) > derot_limit) + if (abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -467,7 +467,7 @@ static void next_sub_range(struct stb0899_state *state) if (internal->sub_dir > 0) { old_sub_range = internal->sub_range; - internal->sub_range = MIN((internal->srch_range / 2) - + internal->sub_range = min((internal->srch_range / 2) - (internal->tuner_offst + internal->sub_range / 2), internal->sub_range); @@ -771,7 +771,7 @@ static long Log2Int(int number) int i; i = 0; - while ((1 << i) <= ABS(number)) + while ((1 << i) <= abs(number)) i++; if (number == 0) diff --git a/drivers/media/dvb/frontends/stb0899_priv.h b/drivers/media/dvb/frontends/stb0899_priv.h index 24619e3689db..82395b912815 100644 --- a/drivers/media/dvb/frontends/stb0899_priv.h +++ b/drivers/media/dvb/frontends/stb0899_priv.h @@ -59,10 +59,6 @@ #define MAKEWORD32(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) #define MAKEWORD16(a, b) (((a) << 8) | (b)) -#define MIN(x, y) ((x) <= (y) ? (x) : (y)) -#define MAX(x, y) ((x) >= (y) ? (x) : (y)) -#define ABS(x) ((x) >= 0 ? (x) : -(x)) - #define LSB(x) ((x & 0xff)) #define MSB(y) ((y >> 8) & 0xff) @@ -168,10 +164,10 @@ struct stb0899_internal { u32 freq; /* Demod internal Frequency */ u32 srate; /* Demod internal Symbol rate */ enum stb0899_fec fecrate; /* Demod internal FEC rate */ - u32 srch_range; /* Demod internal Search Range */ - u32 sub_range; /* Demod current sub range (Hz) */ - u32 tuner_step; /* Tuner step (Hz) */ - u32 tuner_offst; /* Relative offset to carrier (Hz) */ + s32 srch_range; /* Demod internal Search Range */ + s32 sub_range; /* Demod current sub range (Hz) */ + s32 tuner_step; /* Tuner step (Hz) */ + s32 tuner_offst; /* Relative offset to carrier (Hz) */ u32 tuner_bw; /* Current bandwidth of the tuner (Hz) */ s32 mclk; /* Masterclock Divider factor (binary) */ -- cgit v1.2.3 From 1d06059c13fc64b67027334507f734ec0f2f4b6c Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sun, 9 Nov 2008 11:35:13 -0300 Subject: V4L/DVB (10976): Bug fix: For legacy applications stv0899 performs search only first time after insmod. For legacy applications stv0899 performs search only first time after insmod due to not set DVBFE_ALGO_SEARCH_AGAIN bit Signed-off-by: Igor M. Liplianin Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 843407785083..8dcb3fbf7acd 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1290,9 +1290,6 @@ static int dtv_property_process_set(struct dvb_frontend *fe, dprintk("%s() Finalised property cache\n", __func__); dtv_property_cache_submit(fe); - /* Request the search algorithm to search */ - fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; - r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND, &fepriv->parameters); break; @@ -1717,6 +1714,10 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000; fepriv->state = FESTATE_RETUNE; + + /* Request the search algorithm to search */ + fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; + dvb_frontend_wakeup(fe); dvb_frontend_add_event(fe, 0); fepriv->status = 0; -- cgit v1.2.3 From 26f26fa8e3a0822aa43ee0a80bd0196fa2554c42 Mon Sep 17 00:00:00 2001 From: Hans Werner Date: Tue, 27 Jan 2009 16:09:12 -0300 Subject: V4L/DVB (10977): STB6100 init fix, the call to stb6100_set_bandwidth needs an argument in Hz not kHz, and a comment incorrectly says MHz instead of Hz. I don't know if this caused real problems anywhere Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stb6100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/stb6100.c b/drivers/media/dvb/frontends/stb6100.c index ff39275ab49c..1ed5a7db4c5e 100644 --- a/drivers/media/dvb/frontends/stb6100.c +++ b/drivers/media/dvb/frontends/stb6100.c @@ -427,11 +427,11 @@ static int stb6100_init(struct dvb_frontend *fe) status->refclock = 27000000; /* Hz */ status->iqsense = 1; status->bandwidth = 36000; /* kHz */ - state->bandwidth = status->bandwidth * 1000; /* MHz */ + state->bandwidth = status->bandwidth * 1000; /* Hz */ state->reference = status->refclock / 1000; /* kHz */ /* Set default bandwidth. */ - return stb6100_set_bandwidth(fe, status->bandwidth); + return stb6100_set_bandwidth(fe, state->bandwidth); } static int stb6100_get_state(struct dvb_frontend *fe, -- cgit v1.2.3 From a00d0bb86b20a86a72f4df9d6e31dda94c02b4fa Mon Sep 17 00:00:00 2001 From: Matthias Schwarzzot Date: Tue, 27 Jan 2009 16:29:44 -0300 Subject: V4L/DVB (10978): Report tuning algorith correctly Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 29e8f1546ab6..fec1d77fa855 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -1683,7 +1683,7 @@ static int dst_tune_frontend(struct dvb_frontend* fe, static int dst_get_tuning_algo(struct dvb_frontend *fe) { - return dst_algo; + return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW; } static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) -- cgit v1.2.3 From 9fae6c3f648e38f023b99b5f5a5280907b2e796e Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Fri, 13 Mar 2009 09:51:46 -0700 Subject: dnet: replace obsolete *netif_rx_* functions with *napi_* *netif_rx_* functions is obsolete and removed in newer kernels so we need to use corresponding *napi_* functions instead. Signed-off-by: Ilya Yanok Signed-off-by: David S. Miller --- drivers/net/dnet.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c index 4b96974fe76e..5c347f70cb67 100644 --- a/drivers/net/dnet.c +++ b/drivers/net/dnet.c @@ -408,7 +408,7 @@ static int dnet_poll(struct napi_struct *napi, int budget) * packets waiting */ if (!(dnet_readl(bp, RX_FIFO_WCNT) >> 16)) { - netif_rx_complete(napi); + napi_complete(napi); int_enable = dnet_readl(bp, INTR_ENB); int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF; dnet_writel(bp, int_enable, INTR_ENB); @@ -447,7 +447,7 @@ static int dnet_poll(struct napi_struct *napi, int budget) if (npackets < budget) { /* We processed all packets available. Tell NAPI it can * stop polling then re-enable rx interrupts */ - netif_rx_complete(napi); + napi_complete(napi); int_enable = dnet_readl(bp, INTR_ENB); int_enable |= DNET_INTR_SRC_RX_CMDFIFOAF; dnet_writel(bp, int_enable, INTR_ENB); @@ -507,7 +507,7 @@ static irqreturn_t dnet_interrupt(int irq, void *dev_id) } if (int_current & DNET_INTR_SRC_RX_CMDFIFOAF) { - if (netif_rx_schedule_prep(&bp->napi)) { + if (napi_schedule_prep(&bp->napi)) { /* * There's no point taking any more interrupts * until we have processed the buffers @@ -516,7 +516,7 @@ static irqreturn_t dnet_interrupt(int irq, void *dev_id) int_enable = dnet_readl(bp, INTR_ENB); int_enable &= ~DNET_INTR_SRC_RX_CMDFIFOAF; dnet_writel(bp, int_enable, INTR_ENB); - __netif_rx_schedule(&bp->napi); + __napi_schedule(&bp->napi); } handled = 1; } -- cgit v1.2.3 From c3c6496dc3d94d87bb0da86cf0bf48764577bf77 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 11 Mar 2009 11:55:40 +0000 Subject: qlge: bugfix: Increase filter on inbound csum. Chip does not do UDP checksum when fragmentation occurs. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge.h | 1 + drivers/net/qlge/qlge_main.c | 38 ++++++++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h index e6fdce9206cc..aff9c5fec738 100644 --- a/drivers/net/qlge/qlge.h +++ b/drivers/net/qlge/qlge.h @@ -927,6 +927,7 @@ struct ib_mac_iocb_rsp { u8 flags1; #define IB_MAC_IOCB_RSP_OI 0x01 /* Overide intr delay */ #define IB_MAC_IOCB_RSP_I 0x02 /* Disble Intr Generation */ +#define IB_MAC_CSUM_ERR_MASK 0x1c /* A mask to use for csum errs */ #define IB_MAC_IOCB_RSP_TE 0x04 /* Checksum error */ #define IB_MAC_IOCB_RSP_NU 0x08 /* No checksum rcvd */ #define IB_MAC_IOCB_RSP_IE 0x10 /* IPv4 checksum error */ diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 8ea72dc60f79..87787b1ecab2 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1436,18 +1436,32 @@ static void ql_process_mac_rx_intr(struct ql_adapter *qdev, if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_P) { QPRINTK(qdev, RX_STATUS, DEBUG, "Promiscuous Packet.\n"); } - if (ib_mac_rsp->flags1 & (IB_MAC_IOCB_RSP_IE | IB_MAC_IOCB_RSP_TE)) { - QPRINTK(qdev, RX_STATUS, ERR, - "Bad checksum for this %s packet.\n", - ((ib_mac_rsp-> - flags2 & IB_MAC_IOCB_RSP_T) ? "TCP" : "UDP")); - skb->ip_summed = CHECKSUM_NONE; - } else if (qdev->rx_csum && - ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) || - ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && - !(ib_mac_rsp->flags1 & IB_MAC_IOCB_RSP_NU)))) { - QPRINTK(qdev, RX_STATUS, DEBUG, "RX checksum done!\n"); - skb->ip_summed = CHECKSUM_UNNECESSARY; + + skb->protocol = eth_type_trans(skb, ndev); + skb->ip_summed = CHECKSUM_NONE; + + /* If rx checksum is on, and there are no + * csum or frame errors. + */ + if (qdev->rx_csum && + !(ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_ERR_MASK) && + !(ib_mac_rsp->flags1 & IB_MAC_CSUM_ERR_MASK)) { + /* TCP frame. */ + if (ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_T) { + QPRINTK(qdev, RX_STATUS, DEBUG, + "TCP checksum done!\n"); + skb->ip_summed = CHECKSUM_UNNECESSARY; + } else if ((ib_mac_rsp->flags2 & IB_MAC_IOCB_RSP_U) && + (ib_mac_rsp->flags3 & IB_MAC_IOCB_RSP_V4)) { + /* Unfragmented ipv4 UDP frame. */ + struct iphdr *iph = (struct iphdr *) skb->data; + if (!(iph->frag_off & + cpu_to_be16(IP_MF|IP_OFFSET))) { + skb->ip_summed = CHECKSUM_UNNECESSARY; + QPRINTK(qdev, RX_STATUS, DEBUG, + "TCP checksum done!\n"); + } + } } qdev->stats.rx_packets++; qdev->stats.rx_bytes += skb->len; -- cgit v1.2.3 From a7a655f22c75f48e0afe8b86be03ecd70bd68b07 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 11 Mar 2009 11:55:41 +0000 Subject: qlge: bugfix: Tell hw to strip vlan header. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 87787b1ecab2..54d54ea03d49 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -2984,9 +2984,9 @@ static int ql_adapter_initialize(struct ql_adapter *qdev) mask = value << 16; ql_write32(qdev, SYS, mask | value); - /* Set the default queue. */ - value = NIC_RCV_CFG_DFQ; - mask = NIC_RCV_CFG_DFQ_MASK; + /* Set the default queue, and VLAN behavior. */ + value = NIC_RCV_CFG_DFQ | NIC_RCV_CFG_RV; + mask = NIC_RCV_CFG_DFQ_MASK | (NIC_RCV_CFG_RV << 16); ql_write32(qdev, NIC_RCV_CFG, (mask | value)); /* Set the MPI interrupt to enabled. */ -- cgit v1.2.3 From 6612a6344aba8ba7b5af67cd006453bfedbb2967 Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 11 Mar 2009 11:55:42 +0000 Subject: qlge: bugfix: Move netif_napi_del() to common call point. Moving netif_napi_del() up the call chain so it will get called from all exit points. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 54d54ea03d49..00c37c0f8a90 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -3163,6 +3163,11 @@ static int ql_adapter_down(struct ql_adapter *qdev) ql_tx_ring_clean(qdev); + /* Call netif_napi_del() from common point. + */ + for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++) + netif_napi_del(&qdev->rx_ring[i].napi); + spin_lock(&qdev->hw_lock); status = ql_adapter_reset(qdev); if (status) @@ -3867,7 +3872,7 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) { struct net_device *ndev = pci_get_drvdata(pdev); struct ql_adapter *qdev = netdev_priv(ndev); - int err, i; + int err; netif_device_detach(ndev); @@ -3877,9 +3882,6 @@ static int qlge_suspend(struct pci_dev *pdev, pm_message_t state) return err; } - for (i = qdev->rss_ring_first_cq_id; i < qdev->rx_ring_count; i++) - netif_napi_del(&qdev->rx_ring[i].napi); - err = pci_save_state(pdev); if (err) return err; -- cgit v1.2.3 From 855b0993f216a9b0f9cb33573bd05e314105d86c Mon Sep 17 00:00:00 2001 From: Ron Mercer Date: Wed, 11 Mar 2009 11:55:43 +0000 Subject: qlge: bugfix: Pad outbound frames smaller than 60 bytes. With some asic configurations xmit of frames smaller than 60 bytes may fail. Signed-off-by: Ron Mercer Signed-off-by: David S. Miller --- drivers/net/qlge/qlge_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c index 00c37c0f8a90..91191f761fba 100644 --- a/drivers/net/qlge/qlge_main.c +++ b/drivers/net/qlge/qlge_main.c @@ -1941,6 +1941,9 @@ static int qlge_send(struct sk_buff *skb, struct net_device *ndev) tx_ring = &qdev->tx_ring[tx_ring_idx]; + if (skb_padto(skb, ETH_ZLEN)) + return NETDEV_TX_OK; + if (unlikely(atomic_read(&tx_ring->tx_count) < 2)) { QPRINTK(qdev, TX_QUEUED, INFO, "%s: shutting down tx queue %d du to lack of resources.\n", -- cgit v1.2.3 From 9d51af7bd2f1d730cb6eeeb9ff837e3441ad4e07 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Tue, 10 Mar 2009 16:28:51 -0400 Subject: sata_mv: fix MSI irq race condition Fix a (rare) race condition in mv_interrupt() when using MSI. The value of hpriv->main_irq_mask_addr can change on on the fly, and without this patch we could end up writing back a stale copy to the hardware. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 7007edd2d451..74b1080d116d 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -2218,12 +2218,13 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance) else handled = mv_host_intr(host, pending_irqs); } - spin_unlock(&host->lock); /* for MSI: unmask; interrupt cause bits will retrigger now */ if (using_msi) writel(hpriv->main_irq_mask, hpriv->main_irq_mask_addr); + spin_unlock(&host->lock); + return IRQ_RETVAL(handled); } -- cgit v1.2.3 From e3e4385f6181f434c0d786998ad1d0eef4e21c9b Mon Sep 17 00:00:00 2001 From: Stuart MENEFY Date: Tue, 10 Mar 2009 11:38:13 +0000 Subject: libata: Keep shadow last_ctl up to date during resets libata keeps a shadow copy of the ATA CTL register (which is write only), and only writes to the hardware when the required value doesn't match the shadow. However this copy wasn't being maintained when performing reset functions. This could cause problems for the first operation after a reset when the correct value might not be written to the CTL register. This problem was observed when hotplugging a drive: the identify command was being issued with interrupts enabled, when they should have been disabled. Signed-off-by: Stuart Menefy Signed-off-by: Jeff Garzik --- drivers/ata/libata-sff.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 714cb046b594..f93dc029dfde 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -2066,6 +2066,7 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr); udelay(20); /* FIXME: flush */ iowrite8(ap->ctl, ioaddr->ctl_addr); + ap->last_ctl = ap->ctl; /* wait the port to become ready */ return ata_sff_wait_after_reset(&ap->link, devmask, deadline); @@ -2190,8 +2191,10 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes) } /* set up device control */ - if (ap->ioaddr.ctl_addr) + if (ap->ioaddr.ctl_addr) { iowrite8(ap->ctl, ap->ioaddr.ctl_addr); + ap->last_ctl = ap->ctl; + } } EXPORT_SYMBOL_GPL(ata_sff_postreset); @@ -2534,6 +2537,7 @@ void ata_bus_reset(struct ata_port *ap) if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) { /* set up device control for ATA_FLAG_SATA_RESET */ iowrite8(ap->ctl, ioaddr->ctl_addr); + ap->last_ctl = ap->ctl; } DPRINTK("EXIT\n"); -- cgit v1.2.3 From e9c1670c2a14ef9cc20d86b24b829f3947aad34e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 3 Mar 2009 13:52:16 +0900 Subject: ata_piix: add workaround for Samsung DB-P70 Samsung DB-P70 somehow botched the first ICH9 SATA port. The board doesn't expose the first port but somehow SStatus reports link online while failing SRST protocol leading to repeated probe failures and thus long boot delay. Because the BIOS doesn't carry any identifying DMI information, the port can't be blacklisted safely. Fortunately, the controller does have subsystem vendor and ID set. It's unclear whether the subsystem IDs are used only for the board but it can be safely worked around by disabling SIDPR access and just using SRST works around the problem. Even when the workaround is triggered on an unaffected board the only side effect will be missing SCR access. Signed-off-by: Tejun Heo Reported-by: Joseph Jang Reported-by: Jonghyon Sohn Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 54961c0b2c73..ef8b30d577bd 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1289,6 +1289,39 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev, return map; } +static bool piix_no_sidpr(struct ata_host *host) +{ + struct pci_dev *pdev = to_pci_dev(host->dev); + + /* + * Samsung DB-P70 only has three ATA ports exposed and + * curiously the unconnected first port reports link online + * while not responding to SRST protocol causing excessive + * detection delay. + * + * Unfortunately, the system doesn't carry enough DMI + * information to identify the machine but does have subsystem + * vendor and device set. As it's unclear whether the + * subsystem vendor/device is used only for this specific + * board, the port can't be disabled solely with the + * information; however, turning off SIDPR access works around + * the problem. Turn it off. + * + * This problem is reported in bnc#441240. + * + * https://bugzilla.novell.com/show_bug.cgi?id=441420 + */ + if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2920 && + pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG && + pdev->subsystem_device == 0xb049) { + dev_printk(KERN_WARNING, host->dev, + "Samsung DB-P70 detected, disabling SIDPR\n"); + return true; + } + + return false; +} + static int __devinit piix_init_sidpr(struct ata_host *host) { struct pci_dev *pdev = to_pci_dev(host->dev); @@ -1302,6 +1335,10 @@ static int __devinit piix_init_sidpr(struct ata_host *host) if (hpriv->map[i] == IDE) return 0; + /* is it blacklisted? */ + if (piix_no_sidpr(host)) + return 0; + if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR)) return 0; -- cgit v1.2.3 From 3eb76c1ccde496c3c0bfda23d1c803e40b762ce6 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 13 Mar 2009 21:16:12 +0100 Subject: ide-floppy: do not map dataless cmds to an sg since it fails the virt_to_page() translation check with DEBUG_VIRTUAL enabled. Signed-off-by: Borislav Petkov [bart: backport to Linus' tree] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 12 ++++++++++++ drivers/ide/ide-floppy.c | 6 ++++-- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index e96c01260598..e9d042dba0e0 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -140,6 +140,12 @@ static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk, rq->cmd_flags |= REQ_PREEMPT; rq->buffer = (char *)pc; rq->rq_disk = disk; + + if (pc->req_xfer) { + rq->data = pc->buf; + rq->data_len = pc->req_xfer; + } + memcpy(rq->cmd, pc->c, 12); if (drive->media == ide_tape) rq->cmd[13] = REQ_IDETAPE_PC1; @@ -159,6 +165,12 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk, rq = blk_get_request(drive->queue, READ, __GFP_WAIT); rq->cmd_type = REQ_TYPE_SPECIAL; rq->buffer = (char *)pc; + + if (pc->req_xfer) { + rq->data = pc->buf; + rq->data_len = pc->req_xfer; + } + memcpy(rq->cmd, pc->c, 12); if (drive->media == ide_tape) rq->cmd[13] = REQ_IDETAPE_PC1; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 3eab1c6c9b31..317ec62c33d4 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -327,8 +327,10 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, return ide_stopped; } - ide_init_sg_cmd(drive, rq); - ide_map_sg(drive, rq); + if (blk_fs_request(rq) || pc->req_xfer) { + ide_init_sg_cmd(drive, rq); + ide_map_sg(drive, rq); + } pc->sg = hwif->sg_table; pc->sg_cnt = hwif->sg_nents; -- cgit v1.2.3 From 5d82720a7f41f0c877e026c7d17e3bf20ccdbae0 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 13 Mar 2009 21:16:13 +0100 Subject: ide: save the returned value of dma_map_sg dma_map_sg could return a value different to 'nents' argument of dma_map_sg so the ide stack needs to save it for the later usage (e.g. for_each_sg). The ide stack also needs to save the original sg_nents value for pci_unmap_sg. Signed-off-by: FUJITA Tomonori [bart: backport to Linus' tree] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-dma.c | 12 +++++++++--- include/linux/ide.h | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 72ebab0bc755..059c90bb5ad2 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -128,6 +128,7 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = drive->hwif; struct scatterlist *sg = hwif->sg_table; + int i; ide_map_sg(drive, rq); @@ -136,8 +137,13 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq) else hwif->sg_dma_direction = DMA_TO_DEVICE; - return dma_map_sg(hwif->dev, sg, hwif->sg_nents, - hwif->sg_dma_direction); + i = dma_map_sg(hwif->dev, sg, hwif->sg_nents, hwif->sg_dma_direction); + if (i) { + hwif->orig_sg_nents = hwif->sg_nents; + hwif->sg_nents = i; + } + + return i; } EXPORT_SYMBOL_GPL(ide_build_sglist); @@ -156,7 +162,7 @@ void ide_destroy_dmatable(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; - dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents, + dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->orig_sg_nents, hwif->sg_dma_direction); } EXPORT_SYMBOL_GPL(ide_destroy_dmatable); diff --git a/include/linux/ide.h b/include/linux/ide.h index e0cedfe9fad4..25087aead657 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -797,6 +797,7 @@ typedef struct hwif_s { struct scatterlist *sg_table; int sg_max_nents; /* Maximum number of entries in it */ int sg_nents; /* Current number of entries in it */ + int orig_sg_nents; int sg_dma_direction; /* dma transfer direction */ /* data phase of the active command (currently only valid for PIO/DMA) */ -- cgit v1.2.3 From 59f8e169e25c5fce91826412c38359ecaf940b82 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 13 Mar 2009 13:37:46 -0700 Subject: via-velocity: Fix DMA mapping length errors on transmit. From: Dave Jones The dma-debug changes caught that this driver uses the wrong DMA mapping length when skb_padto() does something. With suggestions from Eric Dumazet. Signed-off-by: David S. Miller --- drivers/net/via-velocity.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index c5691fdb7079..fb53ef872df3 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -1838,17 +1838,19 @@ static void velocity_free_tx_buf(struct velocity_info *vptr, struct velocity_td_ { struct sk_buff *skb = tdinfo->skb; int i; + int pktlen; /* * Don't unmap the pre-allocated tx_bufs */ if (tdinfo->skb_dma) { + pktlen = (skb->len > ETH_ZLEN ? : ETH_ZLEN); for (i = 0; i < tdinfo->nskb_dma; i++) { #ifdef VELOCITY_ZERO_COPY_SUPPORT pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], le16_to_cpu(td->tdesc1.len), PCI_DMA_TODEVICE); #else - pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], skb->len, PCI_DMA_TODEVICE); + pci_unmap_single(vptr->pdev, tdinfo->skb_dma[i], pktlen, PCI_DMA_TODEVICE); #endif tdinfo->skb_dma[i] = 0; } @@ -2080,17 +2082,14 @@ static int velocity_xmit(struct sk_buff *skb, struct net_device *dev) struct tx_desc *td_ptr; struct velocity_td_info *tdinfo; unsigned long flags; - int pktlen = skb->len; + int pktlen; __le16 len; int index; - - if (skb->len < ETH_ZLEN) { - if (skb_padto(skb, ETH_ZLEN)) - goto out; - pktlen = ETH_ZLEN; - } + if (skb_padto(skb, ETH_ZLEN)) + goto out; + pktlen = max_t(unsigned int, skb->len, ETH_ZLEN); len = cpu_to_le16(pktlen); -- cgit v1.2.3 From e90d400c2b65c7bf038d3646780f4a81f602cd19 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Tue, 10 Mar 2009 16:00:24 +0000 Subject: ixgbe: fix multiple unicast address support Multiple unicast address support appears to have been broken with the change to support net_device_ops. This a regression from 2.6.28 to 2.6.29. I'm not 100% on whether ndo_set_multicast_list can be NULL after this or not. If ndo_set_rx_mode is set everything _should_ be using it. Signed-off-by: Chris Leech Acked-by: Peter P Waskiewicz Jr Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/ixgbe/ixgbe_main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index d2f4d5f508b7..5d364a96e35d 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -3973,6 +3973,7 @@ static const struct net_device_ops ixgbe_netdev_ops = { .ndo_stop = ixgbe_close, .ndo_start_xmit = ixgbe_xmit_frame, .ndo_get_stats = ixgbe_get_stats, + .ndo_set_rx_mode = ixgbe_set_rx_mode, .ndo_set_multicast_list = ixgbe_set_rx_mode, .ndo_validate_addr = eth_validate_addr, .ndo_set_mac_address = ixgbe_set_mac, -- cgit v1.2.3 From 9616a75505be9b87f9625c4d87d8b07a45ddad4d Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 13 Mar 2009 13:48:46 -0700 Subject: emac: Fix clock control for 405EX and 405EXr chips The EMAC variant in the 405EX and 405EXr chips needs the "440EP" type clock control workaround to avoid lockups of the Rx side during reset. Signed-off-by: Benjamin Herrenschmidt Tested-by: Felix Radensky Signed-off-by: David S. Miller --- drivers/net/ibm_newemac/core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 87a706694fb3..6fd7aa61736e 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -2594,6 +2594,9 @@ static int __devinit emac_init_config(struct emac_instance *dev) if (of_device_is_compatible(np, "ibm,emac-460ex") || of_device_is_compatible(np, "ibm,emac-460gt")) dev->features |= EMAC_FTR_460EX_PHY_CLK_FIX; + if (of_device_is_compatible(np, "ibm,emac-405ex") || + of_device_is_compatible(np, "ibm,emac-405exr")) + dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX; } else if (of_device_is_compatible(np, "ibm,emac4")) { dev->features |= EMAC_FTR_EMAC4; if (of_device_is_compatible(np, "ibm,emac-440gx")) -- cgit v1.2.3 From 1c339eb183bb48095feaa46057ac4f4f0603dbf9 Mon Sep 17 00:00:00 2001 From: Scott James Remnant Date: Fri, 13 Mar 2009 14:30:08 -0700 Subject: sbus: Auto-load openprom module when device opened. The openprom module is missing the char-major-10-139 alias that would cause it to be auto-loaded when a device of that type is opened. This patch adds the alias. Signed-off-by: Scott James Remnant Signed-off-by: Tim Gardner Signed-off-by: David S. Miller --- drivers/sbus/char/openprom.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 29dc735e1a20..124f660a0383 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -51,6 +51,7 @@ MODULE_AUTHOR("Thomas K. Dyas (tdyas@noc.rutgers.edu) and Eddie C. Dost (ecd@sk MODULE_DESCRIPTION("OPENPROM Configuration Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("1.0"); +MODULE_ALIAS_MISCDEV(SUN_OPENPROM_MINOR); /* Private data kept by the driver for each descriptor. */ typedef struct openprom_private_data -- cgit v1.2.3 From 5a89392225c6147d10328a64b06b756561e97edf Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Fri, 13 Mar 2009 15:48:02 -0700 Subject: mv643xx_eth: fix unicast address filter corruption on mtu change When mv643xx_eth_open() is called to up an interface, port_start() will first re-program the unicast address filter, and then re-initialise the PORT_CONFIG register, but that will disable unicast promiscuous mode if it was enabled by the unicast address filter setup. This isn't a problem on ifconfig up, as ->set_rx_mode() will be called shortly afterwards which will program the filters again, but it does trigger when changing the MTU, which calls mv643xx_eth_stop() and then mv643xx_eth_open() by hand to repopulate the receive rings with skbuffs of the new size. Swap the initialisation of the PORT_START register and the call to the unicast filter setup function to fix this. Signed-off-by: Lennert Buytenhek Signed-off-by: David S. Miller --- drivers/net/mv643xx_eth.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 13f11f402a99..b0bc3bc18e9c 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2029,11 +2029,6 @@ static void port_start(struct mv643xx_eth_private *mp) txq_set_fixed_prio_mode(txq); } - /* - * Add configured unicast address to address filter table. - */ - mv643xx_eth_program_unicast_filter(mp->dev); - /* * Receive all unmatched unicast, TCP, UDP, BPDU and broadcast * frames to RX queue #0, and include the pseudo-header when @@ -2046,6 +2041,11 @@ static void port_start(struct mv643xx_eth_private *mp) */ wrlp(mp, PORT_CONFIG_EXT, 0x00000000); + /* + * Add configured unicast addresses to address filter table. + */ + mv643xx_eth_program_unicast_filter(mp->dev); + /* * Enable the receive queues. */ -- cgit v1.2.3 From de9307c68624b03d2922a02a661ce31e20f078cc Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 6 Mar 2009 14:52:12 +0000 Subject: netxen: remove old flash check. Remove flash size check which made sense only for ancient boards with 1MB flash. The check is based on values read from specific locations and fails with firmware size changes. This prevents driver from getting right mac addresses. Signed-off-by: Dhananjay Phadke Signed-off-by: David S. Miller --- drivers/net/netxen/netxen_nic.h | 1 - drivers/net/netxen/netxen_nic_hw.c | 22 ---------------------- drivers/net/netxen/netxen_nic_main.c | 3 --- 3 files changed, 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index f4dd9acb6877..1ff066b2281a 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1595,7 +1595,6 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter) } -int netxen_is_flash_supported(struct netxen_adapter *adapter); int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac); int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac); extern void netxen_change_ringparam(struct netxen_adapter *adapter); diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 821cff68b3f3..7fea77088108 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -706,28 +706,6 @@ int netxen_nic_change_mtu(struct net_device *netdev, int mtu) return rc; } -int netxen_is_flash_supported(struct netxen_adapter *adapter) -{ - const int locs[] = { 0, 0x4, 0x100, 0x4000, 0x4128 }; - int addr, val01, val02, i, j; - - /* if the flash size less than 4Mb, make huge war cry and die */ - for (j = 1; j < 4; j++) { - addr = j * NETXEN_NIC_WINDOW_MARGIN; - for (i = 0; i < ARRAY_SIZE(locs); i++) { - if (netxen_rom_fast_read(adapter, locs[i], &val01) == 0 - && netxen_rom_fast_read(adapter, (addr + locs[i]), - &val02) == 0) { - if (val01 == val02) - return -1; - } else - return -1; - } - } - - return 0; -} - static int netxen_get_flash_block(struct netxen_adapter *adapter, int base, int size, __le32 * buf) { diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 13087782ac40..c172b6e24a96 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -405,9 +405,6 @@ netxen_read_mac_addr(struct netxen_adapter *adapter) struct net_device *netdev = adapter->netdev; struct pci_dev *pdev = adapter->pdev; - if (netxen_is_flash_supported(adapter) != 0) - return -EIO; - if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { if (netxen_p3_get_mac_addr(adapter, &mac_addr) != 0) return -EIO; -- cgit v1.2.3 From bfbd442f69ec9c58590ffc6e93ac8d6809caa48b Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 9 Mar 2009 13:42:24 +0100 Subject: Fix Xilinx SystemACE driver to handle empty CF slot The SystemACE driver does not handle an empty CF slot gracefully. An empty CF slot ends up hanging the system. This patch adds a check for the CF state and stops trying to process requests if the slot is empty. Signed-off-by: Grant Likely Signed-off-by: Jens Axboe --- drivers/block/xsysace.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 381d686fc1a3..119be3442f28 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -489,6 +489,28 @@ static void ace_fsm_dostate(struct ace_device *ace) ace->fsm_state, ace->id_req_count); #endif + /* Verify that there is actually a CF in the slot. If not, then + * bail out back to the idle state and wake up all the waiters */ + status = ace_in32(ace, ACE_STATUS); + if ((status & ACE_STATUS_CFDETECT) == 0) { + ace->fsm_state = ACE_FSM_STATE_IDLE; + ace->media_change = 1; + set_capacity(ace->gd, 0); + dev_info(ace->dev, "No CF in slot\n"); + + /* Drop all pending requests */ + while ((req = elv_next_request(ace->queue)) != NULL) + end_request(req, 0); + + /* Drop back to IDLE state and notify waiters */ + ace->fsm_state = ACE_FSM_STATE_IDLE; + ace->id_result = -EIO; + while (ace->id_req_count) { + complete(&ace->id_completion); + ace->id_req_count--; + } + } + switch (ace->fsm_state) { case ACE_FSM_STATE_IDLE: /* See if there is anything to do */ -- cgit v1.2.3 From 682337fe062e939578d933c74157ae9a36baa4ce Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Sat, 14 Mar 2009 22:26:40 -0700 Subject: igb: remove ASPM L0s workaround The L0s workaround should be moved into a pci quirk and so it is not necessary in the driver. This update removes the L0s workaround from the igb driver. This was the second half of the PCI quirk patch that Matthew Wilcox did not pick up when he picked up the quirk patch. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: David S. Miller --- drivers/net/igb/igb_main.c | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index a50db5398fa5..9dd13ad12ce4 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -1023,11 +1023,10 @@ static int __devinit igb_probe(struct pci_dev *pdev, struct net_device *netdev; struct igb_adapter *adapter; struct e1000_hw *hw; - struct pci_dev *us_dev; const struct e1000_info *ei = igb_info_tbl[ent->driver_data]; unsigned long mmio_start, mmio_len; - int i, err, pci_using_dac, pos; - u16 eeprom_data = 0, state = 0; + int i, err, pci_using_dac; + u16 eeprom_data = 0; u16 eeprom_apme_mask = IGB_EEPROM_APME; u32 part_num; int bars, need_ioport; @@ -1062,27 +1061,6 @@ static int __devinit igb_probe(struct pci_dev *pdev, } } - /* 82575 requires that the pci-e link partner disable the L0s state */ - switch (pdev->device) { - case E1000_DEV_ID_82575EB_COPPER: - case E1000_DEV_ID_82575EB_FIBER_SERDES: - case E1000_DEV_ID_82575GB_QUAD_COPPER: - us_dev = pdev->bus->self; - pos = pci_find_capability(us_dev, PCI_CAP_ID_EXP); - if (pos) { - pci_read_config_word(us_dev, pos + PCI_EXP_LNKCTL, - &state); - state &= ~PCIE_LINK_STATE_L0S; - pci_write_config_word(us_dev, pos + PCI_EXP_LNKCTL, - state); - dev_info(&pdev->dev, - "Disabling ASPM L0s upstream switch port %s\n", - pci_name(us_dev)); - } - default: - break; - } - err = pci_request_selected_regions(pdev, bars, igb_driver_name); if (err) goto err_pci_reg; -- cgit v1.2.3 From 5bee17f18b595937e6beafeee5197868a3f74a06 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Sat, 14 Mar 2009 19:40:59 -0400 Subject: parisc: sba_iommu: fix build bug when CONFIG_PARISC_AGP=y CC drivers/parisc/sba_iommu.o drivers/parisc/sba_iommu.c:1373: error: expected identifier or '(' before '}' token make[2]: *** [drivers/parisc/sba_iommu.o] Error 1 make[1]: *** [drivers/parisc] Error 2 make: *** [drivers] Error 2 Don't know how this has gone missed for so long... clearly I need to do builds on my C8000 more often. Signed-off-by: Kyle McMartin Signed-off-by: Linus Torvalds --- drivers/parisc/sba_iommu.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 6aad8546fd24..e5999c4cedc8 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1367,9 +1367,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ioc->pdir_size /= 2; ioc->pdir_base[PDIR_INDEX(iova_space_size/2)] = SBA_AGPGART_COOKIE; } -} #endif /*SBA_AGP_SUPPORT*/ - } static void -- cgit v1.2.3 From 97d477a914b146e7e6722ded21afa79886ae8ccd Mon Sep 17 00:00:00 2001 From: françois romieu Date: Sun, 15 Mar 2009 01:09:54 +0000 Subject: r8169: use hardware auto-padding. It shortens the code and fixes the current pci_unmap leak with padded skb reported by Dave Jones. Signed-off-by: Francois Romieu Signed-off-by: David S. Miller --- drivers/net/r8169.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index b3473401c83a..352da2a43c9f 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -3363,13 +3363,6 @@ static int rtl8169_start_xmit(struct sk_buff *skb, struct net_device *dev) opts1 |= FirstFrag; } else { len = skb->len; - - if (unlikely(len < ETH_ZLEN)) { - if (skb_padto(skb, ETH_ZLEN)) - goto err_update_stats; - len = ETH_ZLEN; - } - opts1 |= FirstFrag | LastFrag; tp->tx_skb[entry].skb = skb; } @@ -3407,7 +3400,6 @@ out: err_stop: netif_stop_queue(dev); ret = NETDEV_TX_BUSY; -err_update_stats: dev->stats.tx_dropped++; goto out; } -- cgit v1.2.3 From ea8dbdd17099a9a5864ebd4c87e01e657b19c7ab Mon Sep 17 00:00:00 2001 From: françois romieu Date: Sun, 15 Mar 2009 01:10:50 +0000 Subject: r8169: revert "r8169: read MAC address from EEPROM on init (2nd attempt)" It fails on the following systems: - RTL8169sc/8110sc (XID 18000000) reported by Tim Durack (x86) - RTL8169sb/8110sb (XID 10000000) reported by Mikael Pettersson (ARM) The patch appeared to work on x86 for the following systems: RTL8169sb/8110sb 10000000 PCI (EXT) RTL8110s 04000000 PCI (EXT) RTL8102e 24a00000 PCI-E (LOM) RTL8168c/8111c 3c2000c0 PCI-E (LOM) RTL8168b/8111b 38000000 PCI-E (LOM) RTL8168b/8111b 38000000 PCI-E (EXT) The patch exposes two problems: 1) while not completely wrong, mac addresses are not read correctly from the EEPROM 2) the MAC address registers are not correctly set Signed-off-by: Francois Romieu Tested-by: Mikael Pettersson Signed-off-by: David S. Miller --- drivers/net/r8169.c | 114 +--------------------------------------------------- 1 file changed, 2 insertions(+), 112 deletions(-) (limited to 'drivers') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 352da2a43c9f..43fedb9ecedb 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -81,9 +81,9 @@ static const int multicast_filter_limit = 32; #define RTL8169_TX_TIMEOUT (6*HZ) #define RTL8169_PHY_TIMEOUT (10*HZ) -#define RTL_EEPROM_SIG 0x8129 +#define RTL_EEPROM_SIG cpu_to_le32(0x8129) +#define RTL_EEPROM_SIG_MASK cpu_to_le32(0xffff) #define RTL_EEPROM_SIG_ADDR 0x0000 -#define RTL_EEPROM_MAC_ADDR 0x0007 /* write/read MMIO register */ #define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) @@ -293,11 +293,6 @@ enum rtl_register_content { /* Cfg9346Bits */ Cfg9346_Lock = 0x00, Cfg9346_Unlock = 0xc0, - Cfg9346_Program = 0x80, /* Programming mode */ - Cfg9346_EECS = 0x08, /* Chip select */ - Cfg9346_EESK = 0x04, /* Serial data clock */ - Cfg9346_EEDI = 0x02, /* Data input */ - Cfg9346_EEDO = 0x01, /* Data output */ /* rx_mode_bits */ AcceptErr = 0x20, @@ -310,7 +305,6 @@ enum rtl_register_content { /* RxConfigBits */ RxCfgFIFOShift = 13, RxCfgDMAShift = 8, - RxCfg9356SEL = 6, /* EEPROM type: 0 = 9346, 1 = 9356 */ /* TxConfigBits */ TxInterFrameGapShift = 24, @@ -1969,108 +1963,6 @@ static const struct net_device_ops rtl8169_netdev_ops = { }; -/* Delay between EEPROM clock transitions. Force out buffered PCI writes. */ -#define RTL_EEPROM_DELAY() RTL_R8(Cfg9346) -#define RTL_EEPROM_READ_CMD 6 - -/* read 16bit word stored in EEPROM. EEPROM is addressed by words. */ -static u16 rtl_eeprom_read(void __iomem *ioaddr, int addr) -{ - u16 result = 0; - int cmd, cmd_len, i; - - /* check for EEPROM address size (in bits) */ - if (RTL_R32(RxConfig) & (1 << RxCfg9356SEL)) { - /* EEPROM is 93C56 */ - cmd_len = 3 + 8; /* 3 bits for command id and 8 for address */ - cmd = (RTL_EEPROM_READ_CMD << 8) | (addr & 0xff); - } else { - /* EEPROM is 93C46 */ - cmd_len = 3 + 6; /* 3 bits for command id and 6 for address */ - cmd = (RTL_EEPROM_READ_CMD << 6) | (addr & 0x3f); - } - - /* enter programming mode */ - RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); - RTL_EEPROM_DELAY(); - - /* write command and requested address */ - while (cmd_len--) { - u8 x = Cfg9346_Program | Cfg9346_EECS; - - x |= (cmd & (1 << cmd_len)) ? Cfg9346_EEDI : 0; - - /* write a bit */ - RTL_W8(Cfg9346, x); - RTL_EEPROM_DELAY(); - - /* raise clock */ - RTL_W8(Cfg9346, x | Cfg9346_EESK); - RTL_EEPROM_DELAY(); - } - - /* lower clock */ - RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); - RTL_EEPROM_DELAY(); - - /* read back 16bit value */ - for (i = 16; i > 0; i--) { - /* raise clock */ - RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS | Cfg9346_EESK); - RTL_EEPROM_DELAY(); - - result <<= 1; - result |= (RTL_R8(Cfg9346) & Cfg9346_EEDO) ? 1 : 0; - - /* lower clock */ - RTL_W8(Cfg9346, Cfg9346_Program | Cfg9346_EECS); - RTL_EEPROM_DELAY(); - } - - RTL_W8(Cfg9346, Cfg9346_Program); - /* leave programming mode */ - RTL_W8(Cfg9346, Cfg9346_Lock); - - return result; -} - -static void rtl_init_mac_address(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 x; - u8 mac[8]; - - /* read EEPROM signature */ - x = rtl_eeprom_read(ioaddr, RTL_EEPROM_SIG_ADDR); - - if (x != RTL_EEPROM_SIG) { - dev_info(&pdev->dev, "Missing EEPROM signature: %04x\n", x); - return; - } - - /* read MAC address */ - x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR); - mac[0] = x & 0xff; - mac[1] = x >> 8; - x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + 1); - mac[2] = x & 0xff; - mac[3] = x >> 8; - x = rtl_eeprom_read(ioaddr, RTL_EEPROM_MAC_ADDR + 2); - mac[4] = x & 0xff; - mac[5] = x >> 8; - - if (netif_msg_probe(tp)) { - DECLARE_MAC_BUF(buf); - - dev_info(&pdev->dev, "MAC address found in EEPROM: %s\n", - print_mac(buf, mac)); - } - - if (is_valid_ether_addr(mac)) - rtl_rar_set(tp, mac); -} - static int __devinit rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -2249,8 +2141,6 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) tp->mmio_addr = ioaddr; - rtl_init_mac_address(tp, ioaddr); - /* Get MAC address */ for (i = 0; i < MAC_ADDR_LEN; i++) dev->dev_addr[i] = RTL_R8(MAC0 + i); -- cgit v1.2.3 From a140449584522c3eea1bb381f746d40939e6f62a Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Wed, 11 Feb 2009 18:11:22 +0000 Subject: suspend: switch the Asus Pundit P1-AH2 to old ACPI sleep ordering Switch the Asus Pundit P1-AH2 (M2N8L motherboard) to the old ACPI 1.0 sleep ordering by default. Without this it will not suspend/resume correctly. Signed-off-by: Andy Whitcroft Tested-by: Dustin Kirkland Signed-off-by: Len Brown --- drivers/acpi/sleep.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 519266654f06..3ca98686f28b 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -378,6 +378,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), }, }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "M2N8L"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ -- cgit v1.2.3 From 7b46ecd5fcebf381a7bde966db352d8fb1b8e944 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 25 Feb 2009 18:00:18 -0500 Subject: Revert "ACPI: make some IO ports off-limits to AML" This reverts commit 5ec5d38a1c8af255ffc481c81eef13e9155524b3. because it caused spurious dmesg warmings. We'll implement the check for off-limit ports in a more clever way in the future. http://bugzilla.kernel.org/show_bug.cgi?id=12758 Signed-off-by: Len Brown --- drivers/acpi/osl.c | 50 -------------------------------------------------- 1 file changed, 50 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index b3193ec0a2ef..1e35f342957c 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1317,54 +1317,6 @@ acpi_os_validate_interface (char *interface) return AE_SUPPORT; } -#ifdef CONFIG_X86 - -struct aml_port_desc { - uint start; - uint end; - char* name; - char warned; -}; - -static struct aml_port_desc aml_invalid_port_list[] = { - {0x20, 0x21, "PIC0", 0}, - {0xA0, 0xA1, "PIC1", 0}, - {0x4D0, 0x4D1, "ELCR", 0} -}; - -/* - * valid_aml_io_address() - * - * if valid, return true - * else invalid, warn once, return false - */ -static bool valid_aml_io_address(uint address, uint length) -{ - int i; - int entries = sizeof(aml_invalid_port_list) / sizeof(struct aml_port_desc); - - for (i = 0; i < entries; ++i) { - if ((address >= aml_invalid_port_list[i].start && - address <= aml_invalid_port_list[i].end) || - (address + length >= aml_invalid_port_list[i].start && - address + length <= aml_invalid_port_list[i].end)) - { - if (!aml_invalid_port_list[i].warned) - { - printk(KERN_ERR "ACPI: Denied BIOS AML access" - " to invalid port 0x%x+0x%x (%s)\n", - address, length, - aml_invalid_port_list[i].name); - aml_invalid_port_list[i].warned = 1; - } - return false; /* invalid */ - } - } - return true; /* valid */ -} -#else -static inline bool valid_aml_io_address(uint address, uint length) { return true; } -#endif /****************************************************************************** * * FUNCTION: acpi_os_validate_address @@ -1394,8 +1346,6 @@ acpi_os_validate_address ( switch (space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: - if (!valid_aml_io_address(address, length)) - return AE_AML_ILLEGAL_ADDRESS; case ACPI_ADR_SPACE_SYSTEM_MEMORY: /* Only interference checks against SystemIO and SytemMemory are needed */ -- cgit v1.2.3 From 45e7798886af101c4a908a896bbba5a84ee5cc32 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 15 Mar 2009 22:13:44 -0400 Subject: ACPI suspend: Blacklist Toshiba Satellite L300 that requires to set SCI_EN directly on resume This is a supplement of commit 65df78473ffbf3bff5e2034df1638acc4f3ddd50. http://bugzilla.kernel.org/show_bug.cgi?id=12798 Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/sleep.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 3ca98686f28b..00456fccfa38 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -386,6 +386,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "M2N8L"), }, }, + { + .callback = init_set_sci_en_on_resume, + .ident = "Toshiba Satellite L300", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ -- cgit v1.2.3 From 176f9c1804df09f3e9b998c0642e212592ac6283 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 4 Mar 2009 11:55:27 -0800 Subject: ACPI: remove doubled status checking There was a misplaced status test (two consequent tests without a statement in between) in acpi_bus_init for ages. Remove it, since the function which should be checked (acpi_os_initialize1) has BUG_ONs on failure paths. Signed-off-by: Jiri Slaby Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/bus.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 765fd1c56cd6..bee64b73c919 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -758,8 +758,7 @@ static int __init acpi_bus_init(void) acpi_status status = AE_OK; extern acpi_status acpi_os_initialize1(void); - - status = acpi_os_initialize1(); + acpi_os_initialize1(); status = acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE); @@ -769,12 +768,6 @@ static int __init acpi_bus_init(void) goto error1; } - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX - "Unable to initialize ACPI OS objects\n"); - goto error1; - } - /* * ACPI 2.0 requires the EC driver to be loaded and work before * the EC device is found in the namespace (i.e. before acpi_initialize_objects() -- cgit v1.2.3 From 27ce34198345886854643b9572f9a06d2e7500d2 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 4 Mar 2009 11:55:29 -0800 Subject: acpi: check for pxm_to_node_map overflow It is hardly (if ever) possible but in case of broken _PXM entry we could reach out of pxm_to_node_map array bounds in acpi_map_pxm_to_node() call. Signed-off-by: Cyrill Gorcunov Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/numa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index c5e292aab0e3..3a0d8ef25c75 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -277,7 +277,7 @@ int acpi_get_node(acpi_handle *handle) int pxm, node = -1; pxm = acpi_get_pxm(handle); - if (pxm >= 0) + if (pxm >= 0 && pxm < MAX_PXM_DOMAINS) node = acpi_map_pxm_to_node(pxm); return node; -- cgit v1.2.3 From 6050c8dd70b21a9d927983aeb6357fecffa7fb23 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 15 Feb 2009 19:30:19 +0100 Subject: asus-laptop: restore acpi_generate_proc_event() Restore acpi_generate_proc_event() for backward compatibility with old acpi scripts. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/asus-laptop.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 56af6cf385b0..eeafc6c0160d 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -815,6 +815,7 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) { static struct key_entry *key; + u16 count; /* TODO Find a better way to handle events count. */ if (!hotk) @@ -832,9 +833,11 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) lcd_blank(FB_BLANK_POWERDOWN); } + count = hotk->event_count[event % 128]++; + acpi_bus_generate_proc_event(hotk->device, event, count); acpi_bus_generate_netlink_event(hotk->device->pnp.device_class, dev_name(&hotk->device->dev), event, - hotk->event_count[event % 128]++); + count); if (hotk->inputdev) { key = asus_get_entry_by_scancode(event); -- cgit v1.2.3 From 7950b71c3bd7b27b2874088a6c4efe3e13579f8b Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 15 Feb 2009 19:30:20 +0100 Subject: eeepc-laptop: restore acpi_generate_proc_event() Restore acpi_generate_proc_event() for backward compatibility with old acpi scripts. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 786ed8661cb0..6f54fd1757cd 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -557,13 +557,17 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) { static struct key_entry *key; + u16 count; + if (!ehotk) return; if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) notify_brn(); + count = ehotk->event_count[event % 128]++; + acpi_bus_generate_proc_event(ehotk->device, event, count); acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class, dev_name(&ehotk->device->dev), event, - ehotk->event_count[event % 128]++); + count); if (ehotk->inputdev) { key = eepc_get_entry_by_scancode(event); if (key) { -- cgit v1.2.3 From e73e2c62f7646d54e30ef8863ac0be0b8e4ef0eb Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 15 Feb 2009 19:30:21 +0100 Subject: asus-laptop: use select instead of depends on Like thinkpad_acpi or eeepc-laptop, asus-laptop will now use "select" instead of "depends on" for LEDS_CLASS, NEW_LEDS and BACKLIGHT_CLASS_DEVICE Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index b3866ad50227..fede8f327bbd 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -39,9 +39,9 @@ config ASUS_LAPTOP tristate "Asus Laptop Extras (EXPERIMENTAL)" depends on ACPI depends on EXPERIMENTAL && !ACPI_ASUS - depends on LEDS_CLASS - depends on NEW_LEDS - depends on BACKLIGHT_CLASS_DEVICE + select LEDS_CLASS + select NEW_LEDS + select BACKLIGHT_CLASS_DEVICE depends on INPUT ---help--- This is the new Linux driver for Asus laptops. It may also support some -- cgit v1.2.3 From d263da311ab403e3a84fa24920edc826147a550c Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 25 Feb 2009 09:37:09 +0100 Subject: platform/x86: depends instead of select for laptop platform drivers "I hate `select' and will gleefully leap on any s/select/depends/ patch, whether it works or not :)" Andrew Morton select INPUT is not needed here, because if someone doesn't want INPUT, he won't want these drivers either. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index fede8f327bbd..f3ab40188e62 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -185,11 +185,11 @@ config SONYPI_COMPAT config THINKPAD_ACPI tristate "ThinkPad ACPI Laptop Extras" depends on ACPI + depends on INPUT select BACKLIGHT_LCD_SUPPORT select BACKLIGHT_CLASS_DEVICE select HWMON select NVRAM - select INPUT select NEW_LEDS select LEDS_CLASS select NET -- cgit v1.2.3 From 013d67fd4f0da8f6af60a376f1a254266ab658ef Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 14 Feb 2009 09:53:48 +0000 Subject: acer-wmi: double free in acer_rfkill_exit() This is acer_rfkill_exit() from drivers/platform/x86/acer-wmi.c. The code frees wireless_rfkill->data again instead of bluetooth_rfkill->data. This was found using a code checker (http://repo.or.cz/w/smatch.git/). Signed-off-by: Dan Carpenter Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/platform/x86/acer-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 6bcca616a704..a6a42e8c060b 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1026,7 +1026,7 @@ static void acer_rfkill_exit(void) kfree(wireless_rfkill->data); rfkill_unregister(wireless_rfkill); if (has_cap(ACER_CAP_BLUETOOTH)) { - kfree(wireless_rfkill->data); + kfree(bluetooth_rfkill->data); rfkill_unregister(bluetooth_rfkill); } return; -- cgit v1.2.3 From 5fcdd177d063f1d8d569d746ab1bf206b0dfb2e8 Mon Sep 17 00:00:00 2001 From: Carlos Corbacho Date: Sat, 14 Feb 2009 09:53:53 +0000 Subject: acpi-wmi: Unmark as 'experimental' ACPI-WMI isn't experimental anymore, and there are other drivers that now depend on it that aren't either. Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index f3ab40188e62..c2319d97f510 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -315,9 +315,8 @@ config EEEPC_LAPTOP config ACPI_WMI - tristate "WMI (EXPERIMENTAL)" + tristate "WMI" depends on ACPI - depends on EXPERIMENTAL help This driver adds support for the ACPI-WMI (Windows Management Instrumentation) mapper device (PNP0C14) found on some systems. -- cgit v1.2.3 From 54b1ec893e869c815d390afa42aacf1499858112 Mon Sep 17 00:00:00 2001 From: Carlos Corbacho Date: Sat, 14 Feb 2009 09:53:59 +0000 Subject: acer-wmi: Unmark as 'experimental' This driver has been around and used long enough that we can drop the 'experimental'. Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index c2319d97f510..3608081bc3e0 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -15,8 +15,7 @@ menuconfig X86_PLATFORM_DEVICES if X86_PLATFORM_DEVICES config ACER_WMI - tristate "Acer WMI Laptop Extras (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "Acer WMI Laptop Extras" depends on ACPI depends on LEDS_CLASS depends on NEW_LEDS -- cgit v1.2.3 From b36a50f92d1c4300a88f606b4d2bbdc4f442a2d7 Mon Sep 17 00:00:00 2001 From: Mathieu Chouquet-Stringer Date: Sat, 14 Mar 2009 16:35:26 +0100 Subject: thinkpad-acpi: fix module autoloading for older models Looking at the source, there seems to be a missing * to match my DMI string. I mean for newer IBM and Lenovo's laptops you match either one of the following: MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*"); MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*"); While for older Thinkpads, you do this (for instance): IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]"); with IBM_BIOS_MODULE_ALIAS being MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW") Note there's no * terminating the string. As result, udev doesn't load anything because modprobe cannot find anything matching this (my machine actually): udevtest: run: '/sbin/modprobe dmi:bvnIBM:bvr1IET71WW(2.10):bd06/16/2006:svnIBM:pn236621U:pvrNotAv Signed-off-by: Mathieu Chouquet-Stringer Acked-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/platform/x86/thinkpad_acpi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index bcbc05107ba8..d2433204a40c 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -7532,7 +7532,7 @@ MODULE_ALIAS(TPACPI_DRVR_SHORTNAME); * if it is not there yet. */ #define IBM_BIOS_MODULE_ALIAS(__type) \ - MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW") + MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW*") /* Non-ancient thinkpads */ MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*"); @@ -7541,9 +7541,9 @@ MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*"); /* Ancient thinkpad BIOSes have to be identified by * BIOS type or model number, and there are far less * BIOS types than model numbers... */ -IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]"); -IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]"); -IBM_BIOS_MODULE_ALIAS("K[U,X-Z]"); +IBM_BIOS_MODULE_ALIAS("I[BDHIMNOTWVYZ]"); +IBM_BIOS_MODULE_ALIAS("1[0368A-GIKM-PST]"); +IBM_BIOS_MODULE_ALIAS("K[UX-Z]"); MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh"); MODULE_DESCRIPTION(TPACPI_DESC); -- cgit v1.2.3 From da511997d2bbc09f5e39385e0ed209578db07c91 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Wed, 4 Mar 2009 11:55:30 -0800 Subject: acpi-wmi: unsigned cannot be less than 0 include/linux/pci-acpi.h:74: typedef u32 acpi_status; result is unsigned, so an error returned by acpi_bus_register_driver() will not be noticed. Signed-off-by: Roel Kluin Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 8a8b377712c9..2f269e117b8f 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -708,7 +708,7 @@ static int __init acpi_wmi_add(struct acpi_device *device) static int __init acpi_wmi_init(void) { - acpi_status result; + int result; INIT_LIST_HEAD(&wmi_blocks.list); -- cgit v1.2.3 From 8032b526d1a3bd91ad633dd3a3b5fdbc47ad54f1 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 16 Mar 2009 09:05:07 +1030 Subject: linux.conf.au 2009: Tuz Impact: help prevent extinction of species The Tasmanian Devil is a shy iconic Australian creature named for its spine-chilling screech. It is threatened with extinction due to a scientifically interesting but horrific transmissible facial cancer. This one is standing in for Tux for one release using the far less-known Devil Facial Tux Disguise. Save The Tasmanian Devil http://tassiedevil.com.au Signed-off-by: Linux.conf.au Hobart Team Signed-off-by: Rusty Russell Signed-off-by: Linus Torvalds --- Documentation/logo.gif | Bin 16335 -> 0 bytes Documentation/logo.svg | 2911 +++++++++++++++++++ Documentation/logo.txt | 15 +- drivers/video/logo/logo_linux_clut224.ppm | 4428 ++++++++++++++++++----------- drivers/video/logo/logo_linux_vga16.ppm | 4339 +++++++++++++++++----------- 5 files changed, 8477 insertions(+), 3216 deletions(-) delete mode 100644 Documentation/logo.gif create mode 100644 Documentation/logo.svg (limited to 'drivers') diff --git a/Documentation/logo.gif b/Documentation/logo.gif deleted file mode 100644 index 2eae75fecfb9..000000000000 Binary files a/Documentation/logo.gif and /dev/null differ diff --git a/Documentation/logo.svg b/Documentation/logo.svg new file mode 100644 index 000000000000..cb9e4851d8c3 --- /dev/null +++ b/Documentation/logo.svg @@ -0,0 +1,2911 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Documentation/logo.txt b/Documentation/logo.txt index 296f0f7f67eb..a2e62445e28e 100644 --- a/Documentation/logo.txt +++ b/Documentation/logo.txt @@ -1,13 +1,4 @@ -This is the full-colour version of the currently unofficial Linux logo -("currently unofficial" just means that there has been no paperwork and -that I have not really announced it yet). It was created by Larry Ewing, -and is freely usable as long as you acknowledge Larry as the original -artist. - -Note that there are black-and-white versions of this available that -scale down to smaller sizes and are better for letterheads or whatever -you want to use it for: for the full range of logos take a look at -Larry's web-page: - - http://www.isc.tamu.edu/~lewing/linux/ +Tux is taking a three month sabbatical to work as a barber, so Tuz is +standing in. He's taken pains to ensure you'll hardly notice. +Image by Andrew McGown and Josh Bush. Image is licensed CC BY-SA. diff --git a/drivers/video/logo/logo_linux_clut224.ppm b/drivers/video/logo/logo_linux_clut224.ppm index 3c14e43b82fe..de93ff3fc1ad 100644 --- a/drivers/video/logo/logo_linux_clut224.ppm +++ b/drivers/video/logo/logo_linux_clut224.ppm @@ -1,1604 +1,2828 @@ P3 -# Standard 224-color Linux logo -80 80 +145 113 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 - 6 6 6 6 6 6 10 10 10 10 10 10 - 10 10 10 6 6 6 6 6 6 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 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 10 10 10 14 14 14 - 22 22 22 26 26 26 30 30 30 34 34 34 - 30 30 30 30 30 30 26 26 26 18 18 18 - 14 14 14 10 10 10 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 1 0 0 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 - 6 6 6 14 14 14 26 26 26 42 42 42 - 54 54 54 66 66 66 78 78 78 78 78 78 - 78 78 78 74 74 74 66 66 66 54 54 54 - 42 42 42 26 26 26 18 18 18 10 10 10 - 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 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 10 10 10 - 22 22 22 42 42 42 66 66 66 86 86 86 - 66 66 66 38 38 38 38 38 38 22 22 22 - 26 26 26 34 34 34 54 54 54 66 66 66 - 86 86 86 70 70 70 46 46 46 26 26 26 - 14 14 14 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 1 0 0 1 0 0 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 10 10 10 26 26 26 - 50 50 50 82 82 82 58 58 58 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 54 54 54 86 86 86 66 66 66 - 38 38 38 18 18 18 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 6 6 6 22 22 22 50 50 50 - 78 78 78 34 34 34 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 6 6 6 70 70 70 - 78 78 78 46 46 46 22 22 22 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 1 0 0 1 0 0 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 - 6 6 6 18 18 18 42 42 42 82 82 82 - 26 26 26 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 14 14 14 - 46 46 46 34 34 34 6 6 6 2 2 6 - 42 42 42 78 78 78 42 42 42 18 18 18 - 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 1 0 0 0 0 0 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 - 10 10 10 30 30 30 66 66 66 58 58 58 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 26 26 26 - 86 86 86 101 101 101 46 46 46 10 10 10 - 2 2 6 58 58 58 70 70 70 34 34 34 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 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 0 0 1 0 0 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 - 14 14 14 42 42 42 86 86 86 10 10 10 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 30 30 30 - 94 94 94 94 94 94 58 58 58 26 26 26 - 2 2 6 6 6 6 78 78 78 54 54 54 - 22 22 22 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 6 6 6 - 22 22 22 62 62 62 62 62 62 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 26 26 26 - 54 54 54 38 38 38 18 18 18 10 10 10 - 2 2 6 2 2 6 34 34 34 82 82 82 - 38 38 38 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 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 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 0 0 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 6 6 6 - 30 30 30 78 78 78 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 10 10 10 - 10 10 10 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 78 78 78 - 50 50 50 18 18 18 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 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 10 10 10 - 38 38 38 86 86 86 14 14 14 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 54 54 54 - 66 66 66 26 26 26 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 1 0 0 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 14 14 14 - 42 42 42 82 82 82 2 2 6 2 2 6 - 2 2 6 6 6 6 10 10 10 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 6 6 6 - 14 14 14 10 10 10 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 18 18 18 - 82 82 82 34 34 34 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 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 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 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 - 46 46 46 86 86 86 2 2 6 2 2 6 - 6 6 6 6 6 6 22 22 22 34 34 34 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 34 34 34 - 10 10 10 50 50 50 22 22 22 2 2 6 - 2 2 6 2 2 6 2 2 6 10 10 10 - 86 86 86 42 42 42 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 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 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 0 0 1 0 0 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 14 14 14 - 46 46 46 86 86 86 2 2 6 2 2 6 - 38 38 38 116 116 116 94 94 94 22 22 22 - 22 22 22 2 2 6 2 2 6 2 2 6 - 14 14 14 86 86 86 138 138 138 162 162 162 -154 154 154 38 38 38 26 26 26 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 86 86 86 46 46 46 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 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 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 - 46 46 46 86 86 86 2 2 6 14 14 14 -134 134 134 198 198 198 195 195 195 116 116 116 - 10 10 10 2 2 6 2 2 6 6 6 6 -101 98 89 187 187 187 210 210 210 218 218 218 -214 214 214 134 134 134 14 14 14 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 86 86 86 50 50 50 18 18 18 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 1 0 0 0 - 0 0 1 0 0 1 0 0 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 14 14 14 - 46 46 46 86 86 86 2 2 6 54 54 54 -218 218 218 195 195 195 226 226 226 246 246 246 - 58 58 58 2 2 6 2 2 6 30 30 30 -210 210 210 253 253 253 174 174 174 123 123 123 -221 221 221 234 234 234 74 74 74 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 58 58 58 22 22 22 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 14 14 14 - 46 46 46 82 82 82 2 2 6 106 106 106 -170 170 170 26 26 26 86 86 86 226 226 226 -123 123 123 10 10 10 14 14 14 46 46 46 -231 231 231 190 190 190 6 6 6 70 70 70 - 90 90 90 238 238 238 158 158 158 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 58 58 58 22 22 22 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 1 0 0 0 - 0 0 1 0 0 1 0 0 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 14 14 14 - 42 42 42 86 86 86 6 6 6 116 116 116 -106 106 106 6 6 6 70 70 70 149 149 149 -128 128 128 18 18 18 38 38 38 54 54 54 -221 221 221 106 106 106 2 2 6 14 14 14 - 46 46 46 190 190 190 198 198 198 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 62 62 62 22 22 22 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 1 0 0 0 - 0 0 1 0 0 0 0 0 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 14 14 14 - 42 42 42 94 94 94 14 14 14 101 101 101 -128 128 128 2 2 6 18 18 18 116 116 116 -118 98 46 121 92 8 121 92 8 98 78 10 -162 162 162 106 106 106 2 2 6 2 2 6 - 2 2 6 195 195 195 195 195 195 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 62 62 62 22 22 22 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 1 0 0 1 - 0 0 1 0 0 0 0 0 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 10 10 10 - 38 38 38 90 90 90 14 14 14 58 58 58 -210 210 210 26 26 26 54 38 6 154 114 10 -226 170 11 236 186 11 225 175 15 184 144 12 -215 174 15 175 146 61 37 26 9 2 2 6 - 70 70 70 246 246 246 138 138 138 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 66 66 66 26 26 26 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 10 10 10 - 38 38 38 86 86 86 14 14 14 10 10 10 -195 195 195 188 164 115 192 133 9 225 175 15 -239 182 13 234 190 10 232 195 16 232 200 30 -245 207 45 241 208 19 232 195 16 184 144 12 -218 194 134 211 206 186 42 42 42 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 50 50 50 74 74 74 30 30 30 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 10 10 10 - 34 34 34 86 86 86 14 14 14 2 2 6 -121 87 25 192 133 9 219 162 10 239 182 13 -236 186 11 232 195 16 241 208 19 244 214 54 -246 218 60 246 218 38 246 215 20 241 208 19 -241 208 19 226 184 13 121 87 25 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 50 50 50 82 82 82 34 34 34 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 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 - 34 34 34 82 82 82 30 30 30 61 42 6 -180 123 7 206 145 10 230 174 11 239 182 13 -234 190 10 238 202 15 241 208 19 246 218 74 -246 218 38 246 215 20 246 215 20 246 215 20 -226 184 13 215 174 15 184 144 12 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 26 26 26 94 94 94 42 42 42 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 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 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 - 30 30 30 78 78 78 50 50 50 104 69 6 -192 133 9 216 158 10 236 178 12 236 186 11 -232 195 16 241 208 19 244 214 54 245 215 43 -246 215 20 246 215 20 241 208 19 198 155 10 -200 144 11 216 158 10 156 118 10 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 90 90 90 54 54 54 18 18 18 - 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 10 10 10 - 30 30 30 78 78 78 46 46 46 22 22 22 -137 92 6 210 162 10 239 182 13 238 190 10 -238 202 15 241 208 19 246 215 20 246 215 20 -241 208 19 203 166 17 185 133 11 210 150 10 -216 158 10 210 150 10 102 78 10 2 2 6 - 6 6 6 54 54 54 14 14 14 2 2 6 - 2 2 6 62 62 62 74 74 74 30 30 30 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 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 - 34 34 34 78 78 78 50 50 50 6 6 6 - 94 70 30 139 102 15 190 146 13 226 184 13 -232 200 30 232 195 16 215 174 15 190 146 13 -168 122 10 192 133 9 210 150 10 213 154 11 -202 150 34 182 157 106 101 98 89 2 2 6 - 2 2 6 78 78 78 116 116 116 58 58 58 - 2 2 6 22 22 22 90 90 90 46 46 46 - 18 18 18 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 10 10 10 - 38 38 38 86 86 86 50 50 50 6 6 6 -128 128 128 174 154 114 156 107 11 168 122 10 -198 155 10 184 144 12 197 138 11 200 144 11 -206 145 10 206 145 10 197 138 11 188 164 115 -195 195 195 198 198 198 174 174 174 14 14 14 - 2 2 6 22 22 22 116 116 116 116 116 116 - 22 22 22 2 2 6 74 74 74 70 70 70 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 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 18 18 18 - 50 50 50 101 101 101 26 26 26 10 10 10 -138 138 138 190 190 190 174 154 114 156 107 11 -197 138 11 200 144 11 197 138 11 192 133 9 -180 123 7 190 142 34 190 178 144 187 187 187 -202 202 202 221 221 221 214 214 214 66 66 66 - 2 2 6 2 2 6 50 50 50 62 62 62 - 6 6 6 2 2 6 10 10 10 90 90 90 - 50 50 50 18 18 18 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 10 10 10 34 34 34 - 74 74 74 74 74 74 2 2 6 6 6 6 -144 144 144 198 198 198 190 190 190 178 166 146 -154 121 60 156 107 11 156 107 11 168 124 44 -174 154 114 187 187 187 190 190 190 210 210 210 -246 246 246 253 253 253 253 253 253 182 182 182 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 62 62 62 - 74 74 74 34 34 34 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 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 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 22 22 22 54 54 54 - 94 94 94 18 18 18 2 2 6 46 46 46 -234 234 234 221 221 221 190 190 190 190 190 190 -190 190 190 187 187 187 187 187 187 190 190 190 -190 190 190 195 195 195 214 214 214 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 - 82 82 82 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 14 14 14 - 86 86 86 54 54 54 22 22 22 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 - 6 6 6 18 18 18 46 46 46 90 90 90 - 46 46 46 18 18 18 6 6 6 182 182 182 -253 253 253 246 246 246 206 206 206 190 190 190 -190 190 190 190 190 190 190 190 190 190 190 190 -206 206 206 231 231 231 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -202 202 202 14 14 14 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 42 42 42 86 86 86 42 42 42 18 18 18 - 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 6 6 6 - 14 14 14 38 38 38 74 74 74 66 66 66 - 2 2 6 6 6 6 90 90 90 250 250 250 -253 253 253 253 253 253 238 238 238 198 198 198 -190 190 190 190 190 190 195 195 195 221 221 221 -246 246 246 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 82 82 82 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 78 78 78 70 70 70 34 34 34 - 14 14 14 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 14 14 14 - 34 34 34 66 66 66 78 78 78 6 6 6 - 2 2 6 18 18 18 218 218 218 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -226 226 226 231 231 231 246 246 246 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 178 178 178 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 18 18 18 90 90 90 62 62 62 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 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 26 26 26 - 58 58 58 90 90 90 18 18 18 2 2 6 - 2 2 6 110 110 110 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 231 231 231 18 18 18 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 94 94 94 - 54 54 54 26 26 26 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 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 22 22 22 50 50 50 - 90 90 90 26 26 26 2 2 6 2 2 6 - 14 14 14 195 195 195 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 242 242 242 54 54 54 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 38 38 38 - 86 86 86 50 50 50 22 22 22 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 - 6 6 6 14 14 14 38 38 38 82 82 82 - 34 34 34 2 2 6 2 2 6 2 2 6 - 42 42 42 195 195 195 246 246 246 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 242 242 242 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 246 246 246 238 238 238 -226 226 226 231 231 231 101 101 101 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 38 38 38 82 82 82 42 42 42 14 14 14 - 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 - 10 10 10 26 26 26 62 62 62 66 66 66 - 2 2 6 2 2 6 2 2 6 6 6 6 - 70 70 70 170 170 170 206 206 206 234 234 234 -246 246 246 250 250 250 250 250 250 238 238 238 -226 226 226 231 231 231 238 238 238 250 250 250 -250 250 250 250 250 250 246 246 246 231 231 231 -214 214 214 206 206 206 202 202 202 202 202 202 -198 198 198 202 202 202 182 182 182 18 18 18 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 62 62 62 66 66 66 30 30 30 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 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 42 42 42 82 82 82 18 18 18 - 2 2 6 2 2 6 2 2 6 10 10 10 - 94 94 94 182 182 182 218 218 218 242 242 242 -250 250 250 253 253 253 253 253 253 250 250 250 -234 234 234 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -238 238 238 226 226 226 210 210 210 202 202 202 -195 195 195 195 195 195 210 210 210 158 158 158 - 6 6 6 14 14 14 50 50 50 14 14 14 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 86 86 86 46 46 46 - 18 18 18 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 6 6 6 - 22 22 22 54 54 54 70 70 70 2 2 6 - 2 2 6 10 10 10 2 2 6 22 22 22 -166 166 166 231 231 231 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -231 231 231 206 206 206 198 198 198 226 226 226 - 94 94 94 2 2 6 6 6 6 38 38 38 - 30 30 30 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 62 62 62 66 66 66 - 26 26 26 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 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 - 30 30 30 74 74 74 50 50 50 2 2 6 - 26 26 26 26 26 26 2 2 6 106 106 106 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 246 246 246 218 218 218 202 202 202 -210 210 210 14 14 14 2 2 6 2 2 6 - 30 30 30 22 22 22 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 86 86 86 - 42 42 42 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 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 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 - 42 42 42 90 90 90 22 22 22 2 2 6 - 42 42 42 2 2 6 18 18 18 218 218 218 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 250 250 250 221 221 221 -218 218 218 101 101 101 2 2 6 14 14 14 - 18 18 18 38 38 38 10 10 10 2 2 6 - 2 2 6 2 2 6 2 2 6 78 78 78 - 58 58 58 22 22 22 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 6 6 6 18 18 18 - 54 54 54 82 82 82 2 2 6 26 26 26 - 22 22 22 2 2 6 123 123 123 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -238 238 238 198 198 198 6 6 6 38 38 38 - 58 58 58 26 26 26 38 38 38 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 78 78 78 30 30 30 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 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 30 30 30 - 74 74 74 58 58 58 2 2 6 42 42 42 - 2 2 6 22 22 22 231 231 231 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 246 246 246 46 46 46 38 38 38 - 42 42 42 14 14 14 38 38 38 14 14 14 - 2 2 6 2 2 6 2 2 6 6 6 6 - 86 86 86 46 46 46 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 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 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 14 14 14 42 42 42 - 90 90 90 18 18 18 18 18 18 26 26 26 - 2 2 6 116 116 116 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 250 250 250 238 238 238 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 94 94 94 6 6 6 - 2 2 6 2 2 6 10 10 10 34 34 34 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 58 58 58 22 22 22 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 10 10 10 26 26 26 66 66 66 - 82 82 82 2 2 6 38 38 38 6 6 6 - 14 14 14 210 210 210 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 246 246 246 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 144 144 144 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 2 2 6 2 2 6 2 2 6 2 2 6 - 42 42 42 74 74 74 30 30 30 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 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 14 14 14 42 42 42 90 90 90 - 26 26 26 6 6 6 42 42 42 2 2 6 - 74 74 74 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 242 242 242 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 182 182 182 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 2 2 6 2 2 6 2 2 6 2 2 6 - 10 10 10 86 86 86 38 38 38 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 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 26 26 26 66 66 66 82 82 82 - 2 2 6 22 22 22 18 18 18 2 2 6 -149 149 149 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 206 206 206 2 2 6 - 2 2 6 2 2 6 2 2 6 38 38 38 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 86 86 86 46 46 46 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 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 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 - 18 18 18 46 46 46 86 86 86 18 18 18 - 2 2 6 34 34 34 10 10 10 6 6 6 -210 210 210 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 221 221 221 6 6 6 - 2 2 6 2 2 6 6 6 6 30 30 30 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 82 82 82 54 54 54 18 18 18 - 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 10 10 10 - 26 26 26 66 66 66 62 62 62 2 2 6 - 2 2 6 38 38 38 10 10 10 26 26 26 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 238 238 238 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 6 6 6 - 2 2 6 2 2 6 10 10 10 30 30 30 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 58 58 58 22 22 22 - 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 10 10 10 - 38 38 38 78 78 78 6 6 6 2 2 6 - 2 2 6 46 46 46 14 14 14 42 42 42 -246 246 246 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 10 10 10 - 2 2 6 2 2 6 22 22 22 14 14 14 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 62 62 62 22 22 22 - 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 6 6 6 18 18 18 - 50 50 50 74 74 74 2 2 6 2 2 6 - 14 14 14 70 70 70 34 34 34 62 62 62 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 14 14 14 - 2 2 6 2 2 6 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 62 62 62 22 22 22 - 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 6 6 6 18 18 18 - 54 54 54 62 62 62 2 2 6 2 2 6 - 2 2 6 30 30 30 46 46 46 70 70 70 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 226 226 226 10 10 10 - 2 2 6 6 6 6 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 58 58 58 22 22 22 - 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 6 6 6 22 22 22 - 58 58 58 62 62 62 2 2 6 2 2 6 - 2 2 6 2 2 6 30 30 30 78 78 78 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 206 206 206 2 2 6 - 22 22 22 34 34 34 18 14 6 22 22 22 - 26 26 26 18 18 18 6 6 6 2 2 6 - 2 2 6 82 82 82 54 54 54 18 18 18 - 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 6 6 6 26 26 26 - 62 62 62 106 106 106 74 54 14 185 133 11 -210 162 10 121 92 8 6 6 6 62 62 62 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 158 158 158 18 18 18 - 14 14 14 2 2 6 2 2 6 2 2 6 - 6 6 6 18 18 18 66 66 66 38 38 38 - 6 6 6 94 94 94 50 50 50 18 18 18 - 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 6 6 6 - 10 10 10 10 10 10 18 18 18 38 38 38 - 78 78 78 142 134 106 216 158 10 242 186 14 -246 190 14 246 190 14 156 118 10 10 10 10 - 90 90 90 238 238 238 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 230 190 -238 204 91 238 204 91 181 142 44 37 26 9 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 38 38 38 46 46 46 - 26 26 26 106 106 106 54 54 54 18 18 18 - 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 6 6 6 14 14 14 22 22 22 - 30 30 30 38 38 38 50 50 50 70 70 70 -106 106 106 190 142 34 226 170 11 242 186 14 -246 190 14 246 190 14 246 190 14 154 114 10 - 6 6 6 74 74 74 226 226 226 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 228 184 62 -241 196 14 241 208 19 232 195 16 38 30 10 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 30 30 30 26 26 26 -203 166 17 154 142 90 66 66 66 26 26 26 - 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 - 6 6 6 18 18 18 38 38 38 58 58 58 - 78 78 78 86 86 86 101 101 101 123 123 123 -175 146 61 210 150 10 234 174 13 246 186 14 -246 190 14 246 190 14 246 190 14 238 190 10 -102 78 10 2 2 6 46 46 46 198 198 198 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 224 178 62 -242 186 14 241 196 14 210 166 10 22 18 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 6 6 6 121 92 8 -238 202 15 232 195 16 82 82 82 34 34 34 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 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 38 38 38 70 70 70 154 122 46 -190 142 34 200 144 11 197 138 11 197 138 11 -213 154 11 226 170 11 242 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -225 175 15 46 32 6 2 2 6 22 22 22 -158 158 158 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 242 242 242 224 178 62 -239 182 13 236 186 11 213 154 11 46 32 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 61 42 6 225 175 15 -238 190 10 236 186 11 112 100 78 42 42 42 - 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 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 54 54 54 154 122 46 213 154 11 -226 170 11 230 174 11 226 170 11 226 170 11 -236 178 12 242 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -241 196 14 184 144 12 10 10 10 2 2 6 - 6 6 6 116 116 116 242 242 242 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 231 231 231 198 198 198 214 170 54 -236 178 12 236 178 12 210 150 10 137 92 6 - 18 14 6 2 2 6 2 2 6 2 2 6 - 6 6 6 70 47 6 200 144 11 236 178 12 -239 182 13 239 182 13 124 112 88 58 58 58 - 22 22 22 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 10 10 10 - 30 30 30 70 70 70 180 133 36 226 170 11 -239 182 13 242 186 14 242 186 14 246 186 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 232 195 16 98 70 6 2 2 6 - 2 2 6 2 2 6 66 66 66 221 221 221 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 206 206 206 198 198 198 214 166 58 -230 174 11 230 174 11 216 158 10 192 133 9 -163 110 8 116 81 8 102 78 10 116 81 8 -167 114 7 197 138 11 226 170 11 239 182 13 -242 186 14 242 186 14 162 146 94 78 78 78 - 34 34 34 14 14 14 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 6 6 6 - 30 30 30 78 78 78 190 142 34 226 170 11 -239 182 13 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 241 196 14 203 166 17 22 18 6 - 2 2 6 2 2 6 2 2 6 38 38 38 -218 218 218 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 206 206 206 198 198 198 202 162 69 -226 170 11 236 178 12 224 166 10 210 150 10 -200 144 11 197 138 11 192 133 9 197 138 11 -210 150 10 226 170 11 242 186 14 246 190 14 -246 190 14 246 186 14 225 175 15 124 112 88 - 62 62 62 30 30 30 14 14 14 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 10 10 10 - 30 30 30 78 78 78 174 135 50 224 166 10 -239 182 13 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 241 196 14 139 102 15 - 2 2 6 2 2 6 2 2 6 2 2 6 - 78 78 78 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 214 214 214 198 198 198 190 150 46 -219 162 10 236 178 12 234 174 13 224 166 10 -216 158 10 213 154 11 213 154 11 216 158 10 -226 170 11 239 182 13 246 190 14 246 190 14 -246 190 14 246 190 14 242 186 14 206 162 42 -101 101 101 58 58 58 30 30 30 14 14 14 - 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 10 10 10 - 30 30 30 74 74 74 174 135 50 216 158 10 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 241 196 14 226 184 13 - 61 42 6 2 2 6 2 2 6 2 2 6 - 22 22 22 238 238 238 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 226 226 226 187 187 187 180 133 36 -216 158 10 236 178 12 239 182 13 236 178 12 -230 174 11 226 170 11 226 170 11 230 174 11 -236 178 12 242 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 186 14 239 182 13 -206 162 42 106 106 106 66 66 66 34 34 34 - 14 14 14 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 6 6 6 - 26 26 26 70 70 70 163 133 67 213 154 11 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 241 196 14 -190 146 13 18 14 6 2 2 6 2 2 6 - 46 46 46 246 246 246 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 221 221 221 86 86 86 156 107 11 -216 158 10 236 178 12 242 186 14 246 186 14 -242 186 14 239 182 13 239 182 13 242 186 14 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -242 186 14 225 175 15 142 122 72 66 66 66 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 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 - 26 26 26 70 70 70 163 133 67 210 150 10 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -232 195 16 121 92 8 34 34 34 106 106 106 -221 221 221 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -242 242 242 82 82 82 18 14 6 163 110 8 -216 158 10 236 178 12 242 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 242 186 14 163 133 67 - 46 46 46 18 18 18 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 10 10 10 - 30 30 30 78 78 78 163 133 67 210 150 10 -236 178 12 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -241 196 14 215 174 15 190 178 144 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 218 218 218 - 58 58 58 2 2 6 22 18 6 167 114 7 -216 158 10 236 178 12 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 186 14 242 186 14 190 150 46 - 54 54 54 22 22 22 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 14 14 14 - 38 38 38 86 86 86 180 133 36 213 154 11 -236 178 12 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 232 195 16 190 146 13 214 214 214 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 170 170 170 26 26 26 - 2 2 6 2 2 6 37 26 9 163 110 8 -219 162 10 239 182 13 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 236 178 12 224 166 10 142 122 72 - 46 46 46 18 18 18 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 6 6 6 18 18 18 - 50 50 50 109 106 95 192 133 9 224 166 10 -242 186 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -242 186 14 226 184 13 210 162 10 142 110 46 -226 226 226 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -198 198 198 66 66 66 2 2 6 2 2 6 - 2 2 6 2 2 6 50 34 6 156 107 11 -219 162 10 239 182 13 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 242 186 14 -234 174 13 213 154 11 154 122 46 66 66 66 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 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 22 22 22 - 58 58 58 154 121 60 206 145 10 234 174 13 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 236 178 12 210 162 10 163 110 8 - 61 42 6 138 138 138 218 218 218 250 250 250 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 210 210 210 144 144 144 66 66 66 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 61 42 6 163 110 8 -216 158 10 236 178 12 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 239 182 13 230 174 11 216 158 10 -190 142 34 124 112 88 70 70 70 38 38 38 - 18 18 18 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 6 6 6 22 22 22 - 62 62 62 168 124 44 206 145 10 224 166 10 -236 178 12 239 182 13 242 186 14 242 186 14 -246 186 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 236 178 12 216 158 10 175 118 6 - 80 54 7 2 2 6 6 6 6 30 30 30 - 54 54 54 62 62 62 50 50 50 38 38 38 - 14 14 14 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 80 54 7 167 114 7 -213 154 11 236 178 12 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 242 186 14 239 182 13 239 182 13 -230 174 11 210 150 10 174 135 50 124 112 88 - 82 82 82 54 54 54 34 34 34 18 18 18 - 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 6 6 6 18 18 18 - 50 50 50 158 118 36 192 133 9 200 144 11 -216 158 10 219 162 10 224 166 10 226 170 11 -230 174 11 236 178 12 239 182 13 239 182 13 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 230 174 11 210 150 10 163 110 8 -104 69 6 10 10 10 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 91 60 6 167 114 7 -206 145 10 230 174 11 242 186 14 246 190 14 -246 190 14 246 190 14 246 186 14 242 186 14 -239 182 13 230 174 11 224 166 10 213 154 11 -180 133 36 124 112 88 86 86 86 58 58 58 - 38 38 38 22 22 22 10 10 10 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 14 14 14 - 34 34 34 70 70 70 138 110 50 158 118 36 -167 114 7 180 123 7 192 133 9 197 138 11 -200 144 11 206 145 10 213 154 11 219 162 10 -224 166 10 230 174 11 239 182 13 242 186 14 -246 186 14 246 186 14 246 186 14 246 186 14 -239 182 13 216 158 10 185 133 11 152 99 6 -104 69 6 18 14 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 80 54 7 152 99 6 -192 133 9 219 162 10 236 178 12 239 182 13 -246 186 14 242 186 14 239 182 13 236 178 12 -224 166 10 206 145 10 192 133 9 154 121 60 - 94 94 94 62 62 62 42 42 42 22 22 22 - 14 14 14 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 6 6 6 - 18 18 18 34 34 34 58 58 58 78 78 78 -101 98 89 124 112 88 142 110 46 156 107 11 -163 110 8 167 114 7 175 118 6 180 123 7 -185 133 11 197 138 11 210 150 10 219 162 10 -226 170 11 236 178 12 236 178 12 234 174 13 -219 162 10 197 138 11 163 110 8 130 83 6 - 91 60 6 10 10 10 2 2 6 2 2 6 - 18 18 18 38 38 38 38 38 38 38 38 38 - 38 38 38 38 38 38 38 38 38 38 38 38 - 38 38 38 38 38 38 26 26 26 2 2 6 - 2 2 6 6 6 6 70 47 6 137 92 6 -175 118 6 200 144 11 219 162 10 230 174 11 -234 174 13 230 174 11 219 162 10 210 150 10 -192 133 9 163 110 8 124 112 88 82 82 82 - 50 50 50 30 30 30 14 14 14 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 - 6 6 6 14 14 14 22 22 22 34 34 34 - 42 42 42 58 58 58 74 74 74 86 86 86 -101 98 89 122 102 70 130 98 46 121 87 25 -137 92 6 152 99 6 163 110 8 180 123 7 -185 133 11 197 138 11 206 145 10 200 144 11 -180 123 7 156 107 11 130 83 6 104 69 6 - 50 34 6 54 54 54 110 110 110 101 98 89 - 86 86 86 82 82 82 78 78 78 78 78 78 - 78 78 78 78 78 78 78 78 78 78 78 78 - 78 78 78 82 82 82 86 86 86 94 94 94 -106 106 106 101 101 101 86 66 34 124 80 6 -156 107 11 180 123 7 192 133 9 200 144 11 -206 145 10 200 144 11 192 133 9 175 118 6 -139 102 15 109 106 95 70 70 70 42 42 42 - 22 22 22 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 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 10 10 10 - 14 14 14 22 22 22 30 30 30 38 38 38 - 50 50 50 62 62 62 74 74 74 90 90 90 -101 98 89 112 100 78 121 87 25 124 80 6 -137 92 6 152 99 6 152 99 6 152 99 6 -138 86 6 124 80 6 98 70 6 86 66 30 -101 98 89 82 82 82 58 58 58 46 46 46 - 38 38 38 34 34 34 34 34 34 34 34 34 - 34 34 34 34 34 34 34 34 34 34 34 34 - 34 34 34 34 34 34 38 38 38 42 42 42 - 54 54 54 82 82 82 94 86 76 91 60 6 -134 86 6 156 107 11 167 114 7 175 118 6 -175 118 6 167 114 7 152 99 6 121 87 25 -101 98 89 62 62 62 34 34 34 18 18 18 - 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 6 6 6 6 6 6 10 10 10 - 18 18 18 22 22 22 30 30 30 42 42 42 - 50 50 50 66 66 66 86 86 86 101 98 89 -106 86 58 98 70 6 104 69 6 104 69 6 -104 69 6 91 60 6 82 62 34 90 90 90 - 62 62 62 38 38 38 22 22 22 14 14 14 - 10 10 10 10 10 10 10 10 10 10 10 10 - 10 10 10 10 10 10 6 6 6 10 10 10 - 10 10 10 10 10 10 10 10 10 14 14 14 - 22 22 22 42 42 42 70 70 70 89 81 66 - 80 54 7 104 69 6 124 80 6 137 92 6 -134 86 6 116 81 8 100 82 52 86 86 86 - 58 58 58 30 30 30 14 14 14 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 6 6 6 10 10 10 14 14 14 - 18 18 18 26 26 26 38 38 38 54 54 54 - 70 70 70 86 86 86 94 86 76 89 81 66 - 89 81 66 86 86 86 74 74 74 50 50 50 - 30 30 30 14 14 14 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 - 6 6 6 18 18 18 34 34 34 58 58 58 - 82 82 82 89 81 66 89 81 66 89 81 66 - 94 86 66 94 86 76 74 74 74 50 50 50 - 26 26 26 14 14 14 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 - 6 6 6 6 6 6 14 14 14 18 18 18 - 30 30 30 38 38 38 46 46 46 54 54 54 - 50 50 50 42 42 42 30 30 30 18 18 18 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 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 14 14 14 26 26 26 - 38 38 38 50 50 50 58 58 58 58 58 58 - 54 54 54 42 42 42 30 30 30 18 18 18 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 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 - 6 6 6 10 10 10 14 14 14 18 18 18 - 18 18 18 14 14 14 10 10 10 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 6 6 6 - 14 14 14 18 18 18 22 22 22 22 22 22 - 18 18 18 14 14 14 10 10 10 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 4 4 6 7 7 +8 10 10 8 10 10 6 8 8 6 7 7 3 4 4 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 5 5 17 18 17 +27 29 28 35 37 36 40 43 41 43 45 43 40 43 41 37 39 37 +32 34 33 27 30 29 23 25 24 17 21 21 15 18 18 12 15 15 +11 13 13 8 10 10 6 7 7 3 4 4 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 32 34 33 49 51 48 60 60 56 58 59 55 +55 57 54 55 56 53 49 51 48 43 45 43 39 40 39 33 37 35 +28 31 30 23 27 26 20 23 23 17 20 20 14 17 17 13 16 16 +11 14 14 10 13 13 10 12 12 9 11 11 8 10 10 6 7 7 +2 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 7 7 12 15 15 +12 15 15 8 9 9 2 3 3 0 0 0 1 1 1 25 27 26 +55 56 53 68 70 65 65 66 61 65 66 61 63 64 60 63 64 60 +58 59 55 51 52 50 47 48 46 41 42 42 35 37 36 30 32 31 +26 28 27 20 24 24 18 22 22 16 19 19 14 17 17 13 16 16 +12 15 15 11 14 14 10 13 13 10 12 12 9 11 11 8 10 10 +8 9 9 6 8 8 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 7 7 20 24 24 23 27 26 +23 27 26 18 22 22 11 13 13 23 24 24 61 63 57 72 73 67 +72 73 67 68 70 65 68 70 65 68 70 65 63 64 60 58 59 55 +55 56 53 47 48 46 41 42 42 35 37 36 30 32 31 26 28 27 +20 24 24 18 22 22 16 20 20 15 19 19 14 17 17 13 16 16 +12 15 15 12 15 15 11 14 14 10 13 13 10 12 12 9 11 11 +8 10 10 8 9 9 7 9 9 6 7 7 1 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 1 1 1 4 5 5 5 6 5 4 5 5 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 40 41 39 53 55 47 +33 36 34 27 30 29 51 52 50 72 73 67 72 73 67 72 73 67 +72 73 67 68 70 65 68 70 65 63 64 60 58 59 55 51 52 50 +47 48 46 40 43 41 33 37 35 30 32 31 26 28 27 20 24 24 +18 22 22 17 21 21 16 19 19 14 18 18 14 17 17 13 17 17 +13 16 16 12 15 15 12 15 15 11 14 14 10 13 13 10 12 12 +9 11 11 8 10 10 8 9 9 7 9 9 6 8 8 3 4 4 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2 2 2 6 8 8 10 12 12 10 12 12 10 12 12 10 12 12 +6 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 23 23 71 71 57 131 127 93 +115 113 82 63 64 60 72 73 67 72 73 67 72 73 67 72 73 67 +68 70 65 65 66 61 61 63 57 55 57 54 49 51 48 43 45 43 +39 40 39 33 36 34 28 31 30 23 27 26 20 24 24 20 23 23 +17 21 21 16 20 20 15 19 19 15 18 18 14 18 18 14 17 17 +13 17 17 13 16 16 12 15 15 12 15 15 11 14 14 10 13 13 +10 12 12 9 11 11 8 10 10 7 9 9 7 9 9 6 8 8 +4 5 5 0 0 0 0 0 0 0 0 0 1 1 1 6 7 7 +10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +10 12 12 3 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 18 22 22 71 71 57 144 139 99 +84 83 72 68 70 65 72 73 67 72 73 67 68 70 65 65 66 61 +63 64 60 55 57 54 51 52 50 47 48 46 40 43 41 35 37 36 +30 32 31 27 29 28 23 27 26 20 24 24 18 22 22 17 21 21 +16 20 20 15 19 19 15 19 19 15 19 19 15 18 18 14 18 18 +14 17 17 13 17 17 13 16 16 12 15 15 12 15 15 11 14 14 +10 13 13 9 12 12 9 11 11 8 10 10 7 9 9 6 8 8 +6 8 8 3 4 4 0 0 0 2 2 2 8 10 10 10 12 12 +10 12 12 10 12 12 11 13 13 36 38 35 61 61 53 48 49 45 +10 12 12 7 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 61 61 53 84 83 72 +68 70 65 72 73 67 68 70 65 68 70 65 63 64 60 58 59 55 +51 52 50 47 48 46 41 42 42 37 39 37 32 35 33 28 31 30 +23 27 26 20 24 24 20 23 23 18 22 22 17 21 21 17 21 21 +17 21 21 17 21 21 17 20 20 16 20 20 16 20 20 16 19 19 +15 18 18 14 18 18 13 17 17 13 16 16 12 15 15 12 15 15 +11 14 14 10 13 13 9 12 12 9 11 11 8 10 10 7 9 9 +6 8 8 6 8 8 5 6 5 9 11 11 10 12 12 10 12 12 +19 20 18 82 81 62 149 145 103 160 154 106 142 137 94 96 95 69 +10 12 12 10 12 12 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 12 12 44 46 43 68 70 65 +72 73 67 68 70 65 68 70 65 63 64 60 55 57 54 49 51 48 +43 45 43 39 40 39 33 37 35 30 32 31 26 28 27 23 27 26 +20 24 24 18 22 22 18 22 22 18 22 22 18 22 22 20 23 23 +20 24 24 23 25 24 23 25 24 22 24 23 20 23 23 18 22 22 +17 20 20 15 19 19 15 18 18 14 17 17 13 16 16 12 15 15 +11 14 14 11 13 13 10 12 12 9 11 11 8 10 10 8 9 9 +7 9 9 7 9 9 10 12 12 10 12 12 10 12 12 71 71 57 +164 159 111 186 182 128 186 182 128 171 165 117 151 147 98 96 95 69 +10 12 12 10 12 12 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 10 10 63 64 60 68 70 65 +72 73 67 68 70 65 63 64 60 55 57 54 47 48 46 40 43 41 +33 37 35 30 32 31 27 29 28 23 27 26 20 24 24 20 23 23 +18 22 22 18 22 22 20 23 22 21 25 23 23 27 26 27 29 28 +28 31 30 31 33 31 31 33 31 31 33 31 28 31 30 26 28 27 +23 25 24 20 23 22 16 20 20 15 18 18 14 17 17 13 16 16 +12 15 15 11 14 14 10 13 13 10 12 12 9 11 11 8 10 10 +10 12 12 10 13 13 10 12 12 12 14 14 96 95 69 165 161 109 +186 182 128 192 187 134 192 187 134 176 171 126 160 154 106 103 101 77 +10 12 12 10 12 12 5 6 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 35 37 36 68 70 65 72 73 67 +68 70 65 65 66 61 58 59 55 49 51 48 40 43 41 33 37 35 +28 31 30 23 27 26 20 24 24 20 23 23 18 22 22 18 22 22 +18 22 22 20 23 23 23 27 26 27 30 29 32 35 33 37 39 37 +40 43 41 44 46 43 46 47 43 44 46 43 40 43 41 36 38 35 +31 33 31 27 29 28 22 24 23 17 21 21 15 18 18 14 17 17 +13 16 16 12 15 15 11 14 14 11 14 14 11 13 13 13 16 16 +13 16 16 11 14 14 10 12 12 79 78 62 142 137 94 164 159 111 +178 174 128 192 187 134 192 187 134 176 171 126 160 154 106 96 95 69 +10 12 12 10 12 12 6 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 55 57 54 68 70 65 72 73 67 +68 70 65 63 64 60 55 56 53 43 45 43 35 37 36 28 31 30 +23 27 26 20 24 24 18 22 22 17 21 21 17 21 21 17 21 21 +20 24 24 25 27 26 31 33 31 38 39 37 46 47 43 53 55 47 +61 61 53 66 65 55 66 65 55 66 65 55 61 61 53 53 55 47 +46 47 43 37 39 37 30 33 30 24 26 24 17 21 21 15 18 18 +13 17 17 12 15 15 12 15 15 13 16 16 14 18 18 14 18 18 +14 17 17 12 15 15 30 31 28 118 116 76 134 131 96 160 154 106 +174 170 121 178 174 128 178 174 128 171 165 117 151 147 98 96 95 69 +10 12 12 10 12 12 6 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 63 64 60 68 70 65 68 70 65 +65 66 61 58 59 55 49 51 48 39 40 39 30 32 31 23 27 26 +20 24 24 18 22 22 17 21 21 16 20 20 17 21 21 20 23 23 +25 27 26 32 35 33 43 44 41 53 55 47 66 65 55 75 75 61 +82 81 62 84 83 72 87 86 72 87 86 72 82 81 62 75 75 61 +66 65 55 53 55 47 40 41 39 31 33 31 23 25 24 17 20 20 +14 18 18 13 16 16 12 15 15 12 15 15 13 17 17 14 18 18 +14 18 18 13 16 16 46 47 43 96 95 69 125 122 87 142 137 94 +160 154 106 165 161 109 164 159 111 155 149 109 142 137 94 75 75 61 +10 12 12 10 12 12 6 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 60 60 56 68 70 65 68 70 65 +63 64 60 55 57 54 46 47 45 35 37 36 27 30 29 23 25 24 +18 22 22 17 21 21 16 20 20 17 21 21 18 22 22 23 27 26 +31 33 31 43 44 41 55 56 53 71 71 57 84 83 72 92 91 72 +103 101 77 92 91 72 82 81 62 82 81 62 87 86 72 92 91 72 +84 83 72 71 71 57 55 56 53 43 44 41 30 33 30 22 24 23 +16 19 19 14 17 17 12 15 15 12 15 15 13 16 16 14 18 18 +14 18 18 14 17 17 43 44 41 82 81 62 118 116 76 125 122 87 +142 137 94 144 139 99 144 139 99 134 131 96 118 116 76 53 55 47 +10 12 12 10 12 12 6 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 47 48 46 63 64 60 63 64 60 +55 57 54 49 51 48 40 43 41 32 34 33 26 28 27 20 24 24 +18 22 22 16 20 20 16 20 20 17 21 21 20 24 24 28 31 30 +40 41 39 53 55 47 75 75 61 90 89 73 87 86 72 48 49 45 +14 14 13 2 2 2 1 2 2 1 1 1 1 1 1 2 2 2 +19 20 18 43 44 41 66 65 55 53 55 47 38 39 37 26 28 27 +18 22 22 14 18 18 13 16 16 12 15 15 12 15 15 13 17 17 +14 18 18 14 18 18 30 31 28 66 65 55 96 95 69 103 101 77 +118 116 76 118 116 76 118 116 76 118 116 76 103 101 77 36 38 35 +10 12 12 10 12 12 6 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 28 31 30 55 57 54 51 52 50 +49 51 48 41 42 42 35 37 36 28 31 30 23 27 26 20 23 23 +17 21 21 16 20 20 16 20 20 18 22 22 23 27 26 33 36 34 +48 49 45 71 71 57 82 81 62 43 44 41 8 9 9 6 7 7 +6 7 7 6 7 7 6 7 7 5 6 5 4 5 5 3 4 4 +2 3 3 1 2 2 4 5 4 36 38 35 48 49 45 32 35 33 +21 25 23 16 19 19 13 17 17 12 15 15 12 15 15 13 16 16 +14 18 18 14 18 18 16 18 16 36 38 35 61 61 53 82 81 62 +96 95 69 96 95 69 96 95 69 96 95 69 79 78 62 19 20 18 +10 12 12 10 12 12 4 5 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 46 47 45 43 45 43 +40 43 41 35 37 36 30 32 31 23 27 26 20 24 24 18 22 22 +17 21 21 16 20 20 17 21 21 20 23 23 27 30 29 40 41 39 +61 61 53 53 55 47 16 17 16 9 11 11 10 12 12 10 12 12 +10 12 12 10 12 12 10 12 12 9 11 11 8 10 10 8 9 9 +6 8 8 5 6 5 4 5 5 2 3 3 19 20 18 38 39 37 +26 28 27 17 21 21 14 17 17 13 16 16 12 15 15 12 15 15 +13 17 17 14 18 18 12 15 15 13 12 7 30 31 28 46 47 43 +53 55 47 66 65 55 66 65 55 53 55 47 36 38 35 10 12 12 +10 12 12 10 12 12 2 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 33 37 35 35 37 36 +32 35 33 28 31 30 23 27 26 20 24 24 18 22 22 17 21 21 +16 20 20 16 20 20 17 21 21 21 25 23 31 33 31 44 46 43 +31 33 31 11 13 13 12 14 14 12 15 15 13 16 16 14 17 17 +14 17 17 14 17 17 14 17 17 13 16 16 12 15 15 12 14 14 +11 13 13 9 11 11 8 10 10 6 8 8 4 5 5 17 18 17 +30 33 30 20 23 22 15 18 18 13 16 16 12 15 15 12 14 14 +13 16 16 14 17 17 14 18 18 11 12 11 7 7 5 16 17 12 +21 22 20 30 31 28 25 27 25 21 22 20 14 14 13 10 12 12 +10 12 12 9 11 11 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 18 22 22 27 30 29 +27 29 28 40 41 39 53 55 47 53 55 47 53 55 47 46 47 43 +25 27 25 16 20 20 17 21 21 23 25 24 31 33 31 20 20 20 +12 15 15 14 17 17 15 19 19 16 20 20 17 21 21 18 22 22 +18 22 22 18 22 22 18 22 22 17 21 21 17 21 21 16 19 19 +15 18 18 13 16 16 12 15 15 10 12 12 8 10 10 6 8 8 +21 22 21 22 24 23 15 19 19 13 17 17 13 16 16 12 15 15 +12 15 15 13 17 17 14 18 18 14 18 18 13 15 14 10 9 6 +7 7 5 7 7 5 7 7 5 9 11 11 10 12 12 10 12 12 +10 12 12 6 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 17 12 82 81 62 +118 116 76 118 116 76 161 156 96 161 156 96 161 156 96 118 116 76 +118 116 76 96 95 69 53 55 47 22 24 23 14 17 17 13 16 16 +15 19 19 17 21 21 18 22 22 20 24 24 20 24 24 23 27 26 +23 27 26 23 27 26 23 27 26 23 27 26 23 27 26 20 24 24 +20 23 23 17 21 21 16 19 19 14 17 17 12 15 15 10 12 12 +9 11 11 20 23 22 16 19 19 14 17 17 13 16 16 12 15 15 +11 14 14 13 16 16 14 17 17 14 18 18 14 17 17 12 15 15 +10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +9 11 11 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 53 55 47 161 156 96 +161 156 96 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 118 116 76 96 95 69 21 22 20 16 19 19 +18 22 22 20 24 24 23 27 26 23 27 26 26 28 27 27 30 29 +27 30 29 18 22 22 12 14 14 8 10 10 9 11 11 17 21 21 +23 27 26 23 27 26 20 24 24 18 22 22 16 20 20 14 17 17 +12 14 14 14 17 17 16 20 20 14 17 17 13 17 17 13 16 16 +12 15 15 12 15 15 13 17 17 14 18 18 14 17 17 13 16 16 +11 13 13 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +4 5 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 12 7 118 116 76 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 161 156 96 118 116 76 30 31 28 +20 24 24 23 27 26 27 30 29 28 31 30 30 32 31 23 27 26 +16 19 19 17 21 21 12 15 15 9 11 11 10 12 12 9 11 11 +20 24 24 28 31 30 26 28 27 23 27 26 20 24 24 17 21 21 +15 19 19 13 16 16 16 19 19 14 18 18 14 17 17 13 16 16 +12 15 15 11 14 14 13 16 16 14 17 17 14 18 18 14 17 17 +12 15 15 10 12 12 10 12 12 10 12 12 10 12 12 8 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 82 81 62 161 156 96 230 229 82 +230 229 82 233 233 100 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 118 116 76 +27 29 28 27 30 29 30 32 31 30 32 31 23 27 26 20 24 24 +26 28 27 17 21 21 6 7 7 72 73 67 145 141 105 15 15 15 +14 17 17 33 37 35 30 32 31 28 31 30 26 28 27 23 27 26 +20 23 23 16 20 20 15 19 19 14 18 18 14 17 17 13 16 16 +12 15 15 11 14 14 12 15 15 13 17 17 14 18 18 14 17 17 +13 16 16 11 13 13 10 12 12 10 12 12 9 11 11 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +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 17 12 161 156 96 230 229 82 230 229 82 +243 242 120 235 234 117 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 +82 81 62 28 31 30 28 31 30 27 30 29 28 31 30 30 32 31 +33 37 35 13 16 16 3 3 3 105 104 92 210 208 158 12 14 14 +17 21 21 33 37 35 33 37 35 32 35 33 30 32 31 27 30 29 +23 27 26 20 23 23 17 20 20 15 18 18 14 18 18 13 17 17 +13 16 16 12 15 15 11 14 14 13 16 16 14 17 17 14 18 18 +13 17 17 12 15 15 10 12 12 10 12 12 3 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 96 95 69 230 229 82 230 229 82 244 244 132 +241 241 143 243 242 120 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +161 156 96 46 47 43 32 35 33 33 37 35 33 37 35 33 37 35 +40 43 41 23 27 26 1 1 1 2 2 2 24 26 24 14 17 17 +23 27 26 33 37 35 33 37 35 33 37 35 33 37 35 30 32 31 +27 30 29 23 27 26 20 23 23 15 18 18 14 18 18 14 17 17 +13 16 16 12 15 15 11 14 14 12 15 15 13 17 17 14 17 17 +14 17 17 13 16 16 11 13 13 6 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 17 12 161 156 96 230 229 82 235 234 117 239 239 170 +239 239 170 236 236 101 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 118 116 76 33 37 35 33 37 35 37 39 37 37 39 37 +43 45 43 49 51 48 20 24 24 8 10 10 17 20 20 35 37 36 +33 37 35 40 43 41 37 39 37 35 37 36 33 37 35 33 37 35 +30 32 31 27 30 29 23 27 26 15 19 19 14 18 18 14 17 17 +13 17 17 13 16 16 12 15 15 11 14 14 13 16 16 14 17 17 +14 17 17 13 17 17 11 14 14 4 5 5 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 96 95 69 230 229 82 230 229 82 239 239 170 251 251 187 +241 241 143 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 36 38 35 33 37 35 33 37 35 33 37 35 +37 39 37 47 48 46 55 57 54 55 57 54 49 51 48 43 45 43 +43 45 43 43 45 43 40 43 41 40 43 41 37 39 37 33 37 35 +33 37 35 28 31 30 26 28 27 16 20 20 15 18 18 14 18 18 +14 17 17 13 16 16 12 15 15 11 14 14 12 15 15 13 17 17 +14 17 17 14 17 17 8 10 10 5 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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 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 17 12 230 229 82 230 229 82 243 242 120 251 251 187 251 251 187 +246 246 123 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 66 65 55 30 32 31 32 35 33 33 37 35 +33 37 35 37 39 37 40 43 41 47 48 46 49 51 48 51 52 50 +55 57 54 55 57 54 51 52 50 47 48 46 43 45 43 39 40 39 +33 37 35 30 32 31 26 28 27 17 21 21 15 19 19 14 18 18 +14 17 17 13 16 16 12 15 15 12 14 14 11 14 14 13 16 16 +14 17 17 12 15 15 7 9 9 6 8 8 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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +96 95 69 230 229 82 230 229 82 239 239 170 251 251 187 239 239 170 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 96 95 69 27 30 29 28 31 30 30 32 31 +33 37 35 40 43 41 46 47 45 55 57 54 63 64 60 72 73 67 +72 73 67 72 73 67 72 73 67 65 66 61 55 57 54 47 48 46 +39 40 39 32 35 33 27 30 29 17 21 21 15 19 19 15 18 18 +14 18 18 13 17 17 13 16 16 12 15 15 11 14 14 12 14 14 +13 16 16 9 11 11 7 9 9 9 11 11 66 65 55 115 113 82 +21 22 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 12 7 +230 229 82 230 229 82 236 236 101 251 251 187 251 251 187 246 246 123 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 118 116 76 23 27 26 26 28 27 32 35 33 +51 52 50 90 89 73 110 109 94 145 141 105 168 163 120 177 172 135 +177 172 135 188 184 146 188 184 146 181 176 137 194 191 148 188 184 146 +184 179 149 188 184 146 188 184 146 156 151 111 177 172 135 181 176 137 +177 172 135 168 163 120 168 163 120 158 153 112 156 151 111 158 153 112 +156 151 111 158 153 112 177 172 135 188 184 146 188 184 146 194 189 146 +36 38 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 82 81 62 +230 229 82 230 229 82 244 244 132 251 251 187 244 244 132 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 82 81 62 +96 95 69 230 229 82 181 178 103 110 109 94 156 151 111 188 184 146 +188 184 146 197 193 154 188 184 146 184 181 136 188 184 146 168 163 120 +168 163 120 178 174 128 156 151 111 158 153 112 174 170 121 156 151 111 +156 151 111 158 153 112 156 151 111 168 163 120 178 174 128 181 176 137 +176 171 126 178 174 128 184 181 136 176 171 126 178 174 128 184 181 136 +176 171 126 178 174 128 184 181 136 164 159 111 155 149 109 96 95 69 +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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 1 161 156 96 +230 229 82 230 229 82 244 244 132 244 244 132 236 236 101 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 46 47 43 82 81 62 +158 153 112 197 193 154 194 189 146 184 181 136 188 184 146 168 163 120 +156 151 111 137 133 100 131 127 93 137 133 100 137 133 100 158 153 112 +121 119 87 137 133 100 156 151 111 145 141 105 99 98 80 84 83 72 +63 64 60 52 53 49 40 43 41 33 36 34 36 38 35 36 38 35 +38 39 37 43 44 41 43 44 41 46 47 43 48 49 45 48 49 45 +46 47 43 36 38 35 30 31 28 19 20 18 6 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 38 35 230 229 82 +230 229 82 230 229 82 246 246 123 236 236 101 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 53 55 47 121 119 87 +176 171 126 171 165 117 161 156 96 82 81 62 53 55 47 33 37 35 +39 40 39 63 64 60 99 98 80 121 119 87 137 133 100 177 172 135 +176 171 126 184 181 136 131 127 93 131 127 93 110 109 94 84 83 72 +51 52 50 39 40 39 27 29 28 18 22 22 16 19 19 15 19 19 +15 19 19 14 18 18 14 17 17 13 16 16 12 15 15 11 14 14 +10 13 13 9 12 12 9 11 11 8 9 9 7 9 9 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 +230 229 82 230 229 82 236 236 101 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 96 95 69 71 71 57 +36 38 35 118 116 76 118 116 76 12 15 15 15 18 18 20 24 24 +33 37 35 55 56 53 84 83 72 110 109 94 145 141 105 110 109 94 +168 163 120 121 119 87 156 151 111 131 127 93 87 86 72 61 63 57 +47 48 46 28 31 30 18 22 22 15 19 19 15 18 18 15 19 19 +15 19 19 14 18 18 14 17 17 13 17 17 13 16 16 12 15 15 +11 13 13 10 12 12 9 11 11 8 10 10 7 9 9 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 0 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 +161 156 96 230 229 82 118 116 76 11 14 14 14 17 17 18 22 22 +27 30 29 40 43 41 60 60 56 84 83 72 105 104 92 110 109 94 +110 109 94 110 109 94 99 98 80 90 89 73 68 70 65 47 48 46 +32 34 33 23 25 24 20 23 23 17 21 21 15 19 19 14 17 17 +15 19 19 15 18 18 14 18 18 13 17 17 13 16 16 12 15 15 +11 14 14 10 12 12 9 11 11 8 10 10 7 9 9 4 5 5 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 17 12 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 118 116 76 11 13 13 13 16 16 15 19 19 +20 24 24 30 32 31 40 43 41 51 52 50 63 64 60 72 73 67 +65 66 61 65 66 61 65 66 61 55 57 54 46 47 45 33 37 35 +27 29 28 20 24 24 17 21 21 16 20 20 16 20 20 15 19 19 +15 19 19 15 19 19 14 18 18 14 17 17 13 16 16 12 15 15 +11 14 14 10 13 13 9 12 12 8 10 10 7 9 9 6 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 53 55 47 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +161 156 96 118 116 76 53 55 47 10 13 13 12 15 15 14 17 17 +17 20 20 20 24 24 27 29 28 32 34 33 37 39 37 40 43 41 +43 45 43 41 42 42 35 37 36 30 32 31 28 31 30 23 27 26 +20 23 23 17 21 21 16 20 20 16 20 20 16 20 20 16 19 19 +15 19 19 15 19 19 14 18 18 14 17 17 13 16 16 12 15 15 +11 14 14 10 13 13 9 12 12 9 11 11 8 10 10 10 12 12 +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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 82 81 62 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 161 156 96 +118 116 76 82 81 62 13 14 12 10 13 13 12 15 15 13 17 17 +15 19 19 16 20 20 20 23 23 20 24 24 23 27 26 26 28 27 +26 28 27 26 28 27 23 27 26 18 22 22 20 23 23 17 21 21 +17 21 21 16 20 20 16 20 20 16 20 20 16 20 20 16 19 19 +15 19 19 15 19 19 15 18 18 14 17 17 13 17 17 13 16 16 +12 15 15 12 14 14 12 14 14 12 14 14 12 14 14 23 24 24 +6 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 161 156 96 161 156 96 118 116 76 +71 71 57 13 14 12 9 12 12 10 13 13 12 15 15 13 17 17 +15 18 18 15 19 19 16 20 20 17 21 21 17 21 21 18 22 22 +18 22 22 18 22 22 17 21 21 16 19 19 15 18 18 14 18 18 +16 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +15 19 19 15 19 19 15 18 18 14 18 18 16 20 20 23 25 24 +17 21 21 25 27 26 47 48 46 47 48 46 51 52 50 72 73 67 +33 36 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 161 156 96 118 116 76 118 116 76 46 47 43 +9 11 11 9 11 11 10 12 12 11 13 13 12 15 15 14 17 17 +15 18 18 15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +15 19 19 16 20 20 20 24 24 55 56 53 32 34 33 84 83 72 +90 89 73 110 109 94 110 109 94 105 104 92 110 109 94 110 109 94 +72 73 67 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 96 95 69 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 118 116 76 82 81 62 16 17 12 9 11 11 +9 11 11 9 12 12 10 13 13 12 14 14 13 16 16 14 18 18 +15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 19 19 33 36 34 99 98 80 156 151 111 145 141 105 184 179 149 +168 163 120 184 179 149 177 172 135 156 151 111 145 141 105 110 109 94 +90 89 73 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 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 71 71 57 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 230 229 82 230 229 82 230 229 82 161 156 96 +118 116 76 82 81 62 30 31 28 9 11 11 9 11 11 9 11 11 +10 12 12 10 13 13 11 14 14 13 16 16 14 17 17 15 18 18 +15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +18 22 22 58 59 55 137 133 100 197 193 154 214 212 158 210 208 158 +197 193 154 184 179 149 184 179 149 137 133 100 110 109 94 99 98 80 +84 83 72 10 10 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 17 12 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 +161 156 96 161 156 96 161 156 96 161 156 96 118 116 76 71 71 57 +21 22 20 12 14 14 11 13 13 10 12 12 10 12 12 10 13 13 +11 13 13 12 15 15 13 16 16 14 17 17 14 18 18 15 19 19 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 17 21 21 +23 27 26 84 83 72 184 179 149 251 251 187 210 208 158 184 179 149 +184 179 149 156 151 111 110 109 94 84 83 72 63 64 60 51 52 50 +18 22 22 6 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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 161 156 96 +161 156 96 161 156 96 118 116 76 53 55 47 20 23 22 16 19 19 +13 16 16 12 15 15 12 14 14 11 14 14 11 14 14 11 14 14 +12 15 15 13 16 16 14 17 17 15 19 19 16 20 20 17 21 21 +23 27 26 18 22 22 20 24 24 23 27 26 30 32 31 17 21 21 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +23 27 26 33 37 35 137 133 100 156 151 111 158 153 112 105 104 92 +105 104 92 68 70 65 39 40 39 18 22 22 12 14 14 12 15 15 +9 11 11 4 5 5 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 17 12 230 229 82 +230 229 82 230 229 82 230 229 82 161 156 96 118 116 76 118 116 76 +118 116 76 66 65 55 43 45 43 32 34 33 25 27 26 20 23 22 +17 20 20 15 18 18 14 17 17 15 18 18 13 16 16 14 17 17 +14 18 18 16 20 20 32 34 33 55 57 54 58 59 55 72 73 67 +105 104 92 55 57 54 65 66 61 63 64 60 40 43 41 33 37 35 +41 42 42 20 24 24 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +17 21 21 26 28 27 30 32 31 35 37 36 68 70 65 39 40 39 +23 27 26 15 18 18 13 16 16 11 14 14 9 12 12 8 10 10 +7 9 9 6 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 38 35 +230 229 82 230 229 82 230 229 82 96 95 69 30 31 28 49 51 48 +90 89 73 68 70 65 55 57 54 47 48 46 47 48 46 43 45 43 +32 34 33 43 45 43 43 45 43 23 27 26 25 27 26 40 43 41 +40 43 41 90 89 73 110 109 94 145 141 105 156 151 111 156 151 111 +184 179 149 184 179 149 177 172 135 184 179 149 137 133 100 84 83 72 +105 104 92 63 64 60 49 51 48 47 48 46 28 31 30 18 22 22 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 15 19 19 15 19 19 15 19 19 18 22 22 15 19 19 +13 16 16 12 15 15 11 14 14 10 13 13 9 12 12 9 11 11 +8 10 10 6 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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 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 31 28 230 229 82 71 71 57 2 2 1 0 0 0 58 59 55 +105 104 92 84 83 72 65 66 61 84 83 72 110 109 94 110 109 94 +145 141 105 105 104 92 110 109 94 110 109 94 84 83 72 110 109 94 +158 153 112 197 193 154 197 193 154 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 197 193 154 +197 193 154 184 179 149 145 141 105 137 133 100 105 104 92 47 48 46 +20 23 23 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 19 19 15 19 19 15 19 19 14 18 18 14 17 17 +13 17 17 13 16 16 12 14 14 12 14 14 13 13 13 13 13 13 +13 13 13 12 12 12 10 10 9 6 7 7 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +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 0 0 0 0 0 0 0 65 66 61 +105 104 92 84 83 72 84 83 72 110 109 94 184 179 149 210 208 158 +210 208 158 210 208 158 214 212 158 197 193 154 214 212 158 210 208 158 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 251 251 187 184 179 149 84 83 72 +26 28 27 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 15 19 19 15 19 19 15 18 18 14 18 18 +13 17 17 13 16 16 15 15 15 14 14 13 14 14 13 14 14 13 +13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 3 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 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 73 67 +105 104 92 99 98 80 84 83 72 99 98 80 177 172 135 197 193 154 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 214 212 158 197 193 154 99 98 80 +23 27 26 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 15 19 19 15 19 19 15 18 18 14 18 18 +14 17 17 16 16 16 16 16 16 16 16 16 15 15 15 14 14 13 +14 14 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 +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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 83 72 +110 109 94 99 98 80 72 73 67 63 64 60 99 98 80 177 172 135 +184 179 149 210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 210 208 158 184 179 149 177 172 135 110 109 94 33 37 35 +17 21 21 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 15 19 19 15 19 19 15 19 19 14 18 18 +15 18 18 18 19 18 18 19 18 17 17 17 16 16 16 15 15 15 +14 14 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 +10 10 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 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 105 104 92 +108 107 93 99 98 80 72 73 67 63 64 60 51 52 50 87 86 72 +105 104 92 110 109 94 108 107 93 156 151 111 184 179 149 184 179 149 +197 193 154 197 193 154 197 193 154 184 179 149 184 179 149 177 172 135 +197 193 154 156 151 111 177 172 135 184 179 149 168 163 120 137 133 100 +145 141 105 110 109 94 99 98 80 47 48 46 55 57 54 15 19 19 +16 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +17 20 20 17 21 21 16 20 20 16 19 19 15 19 19 16 19 19 +20 20 20 21 22 21 20 20 20 19 20 19 18 19 18 16 16 16 +15 15 15 14 14 13 13 13 13 13 13 13 12 12 12 12 12 12 +12 12 12 4 5 5 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 58 59 55 110 109 94 +105 104 92 90 89 73 72 73 67 55 57 54 43 45 43 39 40 39 +43 45 43 46 47 45 43 45 43 68 70 65 65 66 61 63 64 60 +108 107 93 72 73 67 105 104 92 90 89 73 72 73 67 40 43 41 +72 73 67 68 70 65 68 70 65 58 59 55 63 64 60 49 51 48 +43 45 43 33 36 34 27 30 29 20 24 24 16 20 20 15 19 19 +15 19 19 15 19 19 15 19 19 16 19 19 16 20 20 16 20 20 +17 21 21 20 24 24 20 23 22 17 21 21 17 20 20 20 20 20 +21 22 21 21 22 21 21 22 21 21 22 21 20 20 20 18 19 18 +16 16 16 15 15 15 13 13 13 13 13 13 12 12 12 12 12 12 +12 12 12 10 10 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 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 22 21 110 109 94 110 109 94 +105 104 92 84 83 72 68 70 65 51 52 50 41 42 42 33 37 35 +28 31 30 23 27 26 20 23 23 18 22 22 17 20 20 25 27 26 +26 28 27 27 30 29 25 27 26 20 23 23 23 27 26 30 32 31 +20 24 24 17 21 21 18 22 22 15 19 19 26 28 27 20 23 23 +14 18 18 15 19 19 15 18 18 15 19 19 15 19 19 15 19 19 +15 19 19 15 19 19 15 19 19 15 19 19 15 19 19 16 19 19 +16 20 20 22 24 23 24 26 24 22 24 23 20 23 22 22 24 23 +24 26 24 24 26 24 23 24 24 22 24 23 21 22 21 19 20 19 +17 17 17 15 15 15 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +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 99 98 80 110 109 94 108 107 93 +105 104 92 84 83 72 63 64 60 49 51 48 39 40 39 32 34 33 +27 30 29 23 25 24 20 23 23 17 20 20 15 19 19 14 18 18 +14 17 17 13 17 17 13 17 17 13 17 17 13 17 17 13 17 17 +14 17 17 14 17 17 14 17 17 14 17 17 14 17 17 14 17 17 +14 18 18 14 18 18 14 18 18 14 18 18 15 18 18 15 19 19 +15 19 19 15 19 19 15 19 19 15 19 19 15 19 19 15 19 19 +15 19 19 17 21 21 27 29 28 26 28 27 25 27 26 25 27 26 +27 29 28 27 29 28 26 28 27 24 26 24 21 22 21 20 20 20 +18 19 18 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 4 5 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 51 52 50 110 109 94 110 109 94 105 104 92 +90 89 73 72 73 67 55 57 54 43 45 43 35 37 36 30 32 31 +26 28 27 20 24 24 17 21 21 16 19 19 15 18 18 14 17 17 +13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 +13 16 16 13 16 16 13 16 16 13 17 17 13 17 17 14 17 17 +14 17 17 14 17 17 14 17 17 14 18 18 14 18 18 14 18 18 +15 18 18 15 18 18 15 19 19 15 19 19 15 19 19 15 19 19 +15 19 19 15 19 19 27 29 28 32 34 33 28 31 30 27 29 28 +30 32 31 30 32 31 30 31 28 26 28 27 23 24 24 21 22 21 +19 20 19 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 6 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 9 108 107 93 110 109 94 108 107 93 99 98 80 +84 83 72 63 64 60 49 51 48 40 43 41 33 36 34 27 30 29 +23 27 26 18 22 22 17 20 20 15 18 18 14 17 17 13 16 16 +13 16 16 13 16 16 12 15 15 12 15 15 12 15 15 12 15 15 +13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 +13 17 17 13 17 17 14 17 17 14 17 17 14 17 17 14 18 18 +14 18 18 14 18 18 15 18 18 15 18 18 15 19 19 15 19 19 +15 19 19 15 19 19 17 21 21 33 36 34 32 34 33 31 33 31 +33 36 34 33 36 34 31 33 31 27 29 28 25 27 26 21 22 21 +19 20 19 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 63 64 60 137 133 100 43 45 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 68 70 65 110 109 94 110 109 94 105 104 92 84 83 72 +68 70 65 55 57 54 43 45 43 35 37 36 30 32 31 26 28 27 +20 24 24 17 21 21 16 19 19 14 17 17 13 16 16 12 15 15 +12 15 15 12 15 15 12 15 15 12 15 15 12 15 15 12 15 15 +12 15 15 12 15 15 12 15 15 12 15 15 12 15 15 13 16 16 +13 16 16 13 16 16 13 16 16 13 17 17 13 17 17 14 17 17 +14 17 17 14 17 17 14 18 18 14 18 18 14 18 18 15 18 18 +15 19 19 15 19 19 15 19 19 20 24 24 32 34 33 35 37 36 +37 39 37 35 37 36 33 36 34 30 32 31 26 28 27 22 24 23 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 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 99 98 80 184 179 149 184 179 149 68 70 65 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 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 15 15 110 109 94 110 109 94 108 107 93 99 98 80 72 73 67 +61 63 57 49 51 48 39 40 39 33 36 34 27 30 29 23 25 24 +18 22 22 16 19 19 14 17 17 13 16 16 12 15 15 12 15 15 +11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 +11 14 14 11 14 14 12 14 14 12 15 15 12 15 15 12 15 15 +12 15 15 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 +13 17 17 14 17 17 14 17 17 14 17 17 14 18 18 14 18 18 +14 18 18 15 18 18 15 19 19 15 19 19 30 32 31 38 39 37 +39 40 39 39 40 39 35 37 36 31 33 31 27 29 28 22 24 23 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 +110 109 94 197 193 154 210 208 158 184 179 149 68 70 65 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +68 70 65 110 109 94 110 109 94 105 104 92 84 83 72 65 66 61 +51 52 50 43 45 43 35 37 36 30 32 31 25 27 26 20 23 23 +17 20 20 15 18 18 13 16 16 12 15 15 12 15 15 11 14 14 +11 14 14 11 14 14 11 13 13 11 13 13 11 13 13 11 13 13 +11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 +12 15 15 12 15 15 12 15 15 12 15 15 13 16 16 13 16 16 +13 16 16 13 16 16 13 17 17 13 17 17 14 17 17 14 17 17 +14 18 18 14 18 18 14 18 18 16 19 19 37 39 37 41 42 42 +41 42 42 41 42 42 38 39 37 32 34 33 27 29 28 23 24 24 +21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 11 11 11 137 133 100 +197 193 154 251 251 187 239 239 170 184 179 149 31 33 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 +110 109 94 110 109 94 105 104 92 90 89 73 72 73 67 58 59 55 +46 47 45 37 39 37 31 33 31 26 28 27 20 24 24 17 21 21 +15 18 18 13 16 16 12 15 15 12 14 14 11 13 13 11 13 13 +10 13 13 10 13 13 10 13 13 10 13 13 10 13 13 10 13 13 +10 13 13 10 13 13 11 13 13 11 13 13 11 14 14 11 14 14 +11 14 14 11 14 14 12 14 14 12 15 15 12 15 15 12 15 15 +13 16 16 13 16 16 13 16 16 13 16 16 13 17 17 13 17 17 +14 17 17 14 17 17 14 18 18 23 27 26 41 42 42 41 42 42 +43 45 43 41 42 42 39 40 39 33 36 34 27 29 28 23 24 24 +21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 6 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 27 29 28 168 163 120 210 208 158 +251 251 187 251 251 187 210 208 158 137 133 100 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 60 60 56 +110 109 94 105 104 92 105 104 92 84 83 72 65 66 61 51 52 50 +40 43 41 33 36 34 27 30 29 23 25 24 18 22 22 16 19 19 +14 17 17 12 15 15 11 14 14 11 14 14 10 13 13 10 13 13 +10 13 13 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +10 12 12 10 12 12 10 13 13 10 13 13 10 13 13 11 13 13 +11 13 13 11 14 14 11 14 14 11 14 14 11 14 14 12 15 15 +12 15 15 12 15 15 12 15 15 13 16 16 13 16 16 13 16 16 +13 17 17 13 17 17 14 17 17 32 34 33 43 45 43 43 45 43 +43 45 43 43 45 43 39 40 39 33 36 34 27 29 28 23 24 24 +21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 6 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 68 70 65 184 179 149 210 208 158 251 251 187 +251 251 187 214 212 158 184 179 149 37 39 37 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 7 7 105 104 92 +105 104 92 105 104 92 99 98 80 72 73 67 58 59 55 46 47 45 +35 37 36 30 32 31 25 27 26 20 23 23 16 19 19 14 17 17 +12 15 15 12 14 14 11 13 13 10 13 13 10 12 12 10 12 12 +10 12 12 10 12 12 9 12 12 9 12 12 9 12 12 9 12 12 +10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 13 13 +10 13 13 10 13 13 11 13 13 11 13 13 11 14 14 11 14 14 +11 14 14 12 15 15 12 15 15 12 15 15 12 15 15 13 16 16 +13 16 16 13 16 16 17 20 20 41 42 42 46 47 45 46 47 45 +46 47 45 43 45 43 40 41 39 33 36 34 27 29 28 23 24 24 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 4 5 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 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 15 15 110 109 94 197 193 154 214 212 158 251 251 187 251 251 187 +239 239 170 184 179 149 84 83 72 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 47 48 46 105 104 92 +105 104 92 99 98 80 84 83 72 68 70 65 51 52 50 40 43 41 +32 34 33 27 29 28 22 24 23 17 21 21 15 18 18 13 16 16 +12 15 15 11 13 13 10 13 13 10 12 12 9 12 12 9 12 12 +9 12 12 9 12 12 9 11 11 9 11 11 9 11 11 9 11 11 +9 12 12 9 12 12 9 12 12 9 12 12 10 12 12 10 12 12 +10 12 12 10 12 12 10 13 13 10 13 13 10 13 13 11 13 13 +11 14 14 11 14 14 11 14 14 12 14 14 12 15 15 12 15 15 +12 15 15 13 16 16 28 31 30 43 45 43 47 48 46 47 48 46 +47 48 46 43 45 43 40 41 39 33 36 34 27 29 28 22 24 23 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 3 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 1 1 1 60 60 56 +177 172 135 197 193 154 251 251 187 251 251 187 251 251 187 251 251 187 +184 179 149 110 109 94 3 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 1 1 1 99 98 80 105 104 92 +99 98 80 87 86 72 84 83 72 63 64 60 46 47 45 35 37 36 +30 32 31 25 27 26 18 22 22 16 19 19 14 17 17 12 15 15 +11 14 14 10 13 13 9 12 12 9 12 12 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 12 12 9 12 12 +9 12 12 10 12 12 10 12 12 10 12 12 10 13 13 10 13 13 +10 13 13 11 13 13 11 14 14 11 14 14 11 14 14 12 15 15 +12 15 15 14 17 17 41 42 42 47 48 46 49 51 48 51 52 50 +47 48 46 43 45 43 40 41 39 33 36 34 27 29 28 22 24 23 +19 20 19 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 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 23 24 24 137 133 100 184 179 149 +210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 184 179 149 +110 109 94 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 30 32 31 105 104 92 99 98 80 +84 83 72 84 83 72 72 73 67 55 57 54 41 42 42 32 34 33 +27 29 28 20 24 24 17 20 20 14 17 17 13 16 16 12 14 14 +10 13 13 10 12 12 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 12 12 9 12 12 10 12 12 10 12 12 10 12 12 +10 13 13 10 13 13 10 13 13 11 13 13 11 14 14 11 14 14 +11 14 14 27 29 28 55 56 53 72 73 67 51 52 50 51 52 50 +49 51 48 43 45 43 39 40 39 32 34 33 26 28 27 21 22 21 +19 20 19 16 16 16 18 19 17 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 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 8 8 7 84 83 72 184 179 149 197 193 154 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 184 179 149 145 141 105 +19 20 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 13 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 72 73 67 105 104 92 84 83 72 +72 73 67 84 83 72 68 70 65 49 51 48 39 40 39 30 32 31 +25 27 26 18 22 22 15 18 18 13 16 16 12 15 15 11 13 13 +10 12 12 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 12 12 9 12 12 9 12 12 +10 12 12 10 12 12 10 12 12 10 13 13 10 13 13 11 13 13 +13 16 16 41 42 42 99 98 80 158 153 112 65 66 61 51 52 50 +49 51 48 43 45 43 39 40 39 31 33 31 25 27 26 21 22 21 +21 22 21 68 70 65 55 56 53 13 13 13 12 12 12 12 12 12 +12 12 12 11 11 11 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 +63 64 60 158 153 112 184 179 149 210 208 158 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 184 179 149 137 133 100 27 29 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 +21 22 21 110 109 94 5 6 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 13 13 13 105 104 92 90 89 73 72 73 67 +68 70 65 84 83 72 63 64 60 46 47 45 35 37 36 27 29 28 +22 24 23 17 20 20 14 17 17 12 15 15 11 14 14 10 12 12 +10 12 12 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 12 12 9 12 12 10 12 12 10 12 12 10 13 13 10 13 13 +30 32 31 47 48 46 177 172 135 210 208 158 137 133 100 55 56 53 +49 51 48 43 45 43 38 39 37 31 33 31 25 27 26 22 24 23 +110 109 94 184 179 149 63 64 60 13 13 13 12 12 12 12 12 12 +12 12 12 8 9 9 0 0 0 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 21 22 21 105 104 92 +184 179 149 210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 184 179 149 145 141 105 23 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 +68 70 65 184 179 149 105 104 92 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 51 52 50 99 98 80 84 83 72 63 64 60 +68 70 65 72 73 67 55 57 54 41 42 42 32 34 33 25 27 26 +20 23 23 16 19 19 13 16 16 12 14 14 10 13 13 10 12 12 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 12 12 9 12 12 10 12 12 17 20 20 +46 47 45 72 73 67 210 208 158 251 251 187 210 208 158 63 64 60 +49 51 48 43 45 43 37 39 37 30 32 31 24 26 24 105 104 92 +210 208 158 197 193 154 47 48 46 13 13 13 12 12 12 12 12 12 +12 12 12 6 7 7 33 36 34 48 49 45 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +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 7 23 24 24 55 56 53 110 109 94 +210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 184 179 149 110 109 94 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 +110 109 94 251 251 187 210 208 158 47 48 46 0 0 0 0 0 0 +0 0 0 1 1 1 90 89 73 90 89 73 72 73 67 55 56 53 +72 73 67 68 70 65 51 52 50 37 39 37 28 31 30 23 25 24 +17 21 21 15 18 18 12 15 15 11 14 14 10 13 13 9 12 12 +9 11 11 9 11 11 9 11 11 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 12 12 13 16 16 41 42 42 +49 51 48 110 109 94 251 251 187 251 251 187 251 251 187 105 104 92 +49 51 48 43 45 43 35 37 36 30 31 28 47 48 46 197 193 154 +251 251 187 197 193 154 31 33 31 12 12 12 12 12 12 12 12 12 +12 12 12 51 52 50 184 179 149 72 73 67 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 +11 11 11 21 22 21 30 32 31 40 41 39 60 60 56 145 141 105 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158 +184 179 149 110 109 94 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 4 5 4 61 61 53 48 49 45 3 4 3 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +156 151 111 251 251 187 251 251 187 184 179 149 11 11 11 0 0 0 +0 0 0 26 28 27 99 98 80 84 83 72 60 60 56 43 45 43 +72 73 67 65 66 61 49 51 48 35 37 36 27 29 28 20 24 24 +17 20 20 14 17 17 12 15 15 11 13 13 10 12 12 9 11 11 +9 11 11 9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 11 13 13 37 39 37 47 48 46 +51 52 50 184 179 149 251 251 187 251 251 187 251 251 187 145 141 105 +47 48 46 41 42 42 35 37 36 27 29 28 137 133 100 251 251 187 +251 251 187 197 193 154 19 20 19 12 12 12 12 12 12 12 12 12 +27 29 28 184 179 149 214 212 158 63 64 60 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +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 6 7 7 16 16 16 24 26 24 +30 32 31 38 39 37 47 48 46 55 57 54 68 70 65 110 109 94 +197 193 154 251 251 187 251 251 187 251 251 187 210 208 158 184 179 149 +105 104 92 8 8 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 +0 0 0 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 66 61 184 179 149 156 151 111 +30 32 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +168 163 120 251 251 187 251 251 187 251 251 187 110 109 94 0 0 0 +0 0 0 60 60 56 84 83 72 68 70 65 51 52 50 38 39 37 +84 83 72 63 64 60 43 45 43 33 36 34 25 27 26 20 23 22 +15 18 18 13 16 16 12 14 14 10 13 13 9 12 12 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +9 11 11 9 11 11 10 12 12 33 36 34 46 47 45 51 52 50 +72 73 67 210 208 158 251 251 187 251 251 187 251 251 187 177 172 135 +47 48 46 41 42 42 35 37 36 37 39 37 184 179 149 251 251 187 +251 251 187 197 193 154 13 13 13 12 12 12 12 12 12 12 12 12 +110 109 94 251 251 187 251 251 187 37 39 37 0 0 0 0 0 0 +0 0 0 21 22 20 2 2 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 +4 5 5 12 12 12 21 22 21 25 27 26 30 32 31 38 39 37 +46 47 45 55 56 53 60 60 56 65 66 61 68 70 65 105 104 92 +110 109 94 197 193 154 210 208 158 197 193 154 184 179 149 84 83 72 +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 13 13 13 184 179 149 251 251 187 +197 193 154 43 44 41 0 0 0 0 0 0 0 0 0 0 0 0 +145 141 105 251 251 187 251 251 187 251 251 187 214 212 158 43 45 43 +2 2 2 84 83 72 72 73 67 58 59 55 41 42 42 38 39 37 +72 73 67 58 59 55 41 42 42 31 33 31 25 27 26 18 22 22 +14 17 17 12 15 15 12 14 14 10 12 12 9 12 12 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 9 12 12 31 33 31 43 45 43 49 51 48 55 56 53 +110 109 94 251 251 187 251 251 187 251 251 187 251 251 187 168 163 120 +47 48 46 41 42 42 33 36 34 63 64 60 197 193 154 251 251 187 +251 251 187 184 179 149 13 13 13 12 12 12 12 12 12 16 16 16 +197 193 154 251 251 187 239 239 170 20 20 20 0 0 0 2 2 1 +108 107 93 110 109 94 0 0 0 0 0 0 0 0 0 0 0 0 +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 5 5 11 11 11 18 19 18 +22 24 23 26 28 27 32 34 33 39 40 39 46 47 45 51 52 50 +55 57 54 60 60 56 63 64 60 63 64 60 63 64 60 58 59 55 +63 64 60 99 98 80 145 141 105 137 133 100 43 45 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 3 4 3 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 110 109 94 251 251 187 +251 251 187 184 179 149 25 27 26 0 0 0 0 0 0 0 0 0 +99 98 80 251 251 187 251 251 187 251 251 187 251 251 187 156 151 111 +25 27 26 84 83 72 65 66 61 47 48 46 32 34 33 39 40 39 +72 73 67 55 57 54 40 41 39 30 32 31 23 25 24 18 22 22 +14 17 17 12 15 15 11 13 13 10 12 12 9 11 11 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +9 11 11 28 31 30 41 42 42 47 48 46 55 56 53 58 59 55 +137 133 100 251 251 187 251 251 187 251 251 187 210 208 158 137 133 100 +47 48 46 40 41 39 32 34 33 75 75 61 184 179 149 239 239 170 +251 251 187 177 172 135 13 13 13 12 12 12 12 12 12 43 44 41 +197 193 154 251 251 187 210 208 158 10 10 9 0 0 0 84 83 72 +251 251 187 84 83 72 0 0 0 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 +6 7 7 11 11 11 17 17 17 20 20 20 23 24 24 27 29 28 +32 34 33 38 39 37 43 45 43 47 48 46 51 52 50 55 56 53 +58 59 55 58 59 55 55 57 54 55 56 53 47 48 46 41 42 42 +35 37 36 31 33 31 47 48 46 14 14 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 66 65 55 99 98 80 20 20 20 +0 0 0 0 0 0 0 0 0 0 0 0 43 45 43 214 212 158 +251 251 187 251 251 187 145 141 105 3 3 3 0 0 0 0 0 0 +48 49 45 184 179 149 239 239 170 251 251 187 239 239 170 177 172 135 +84 83 72 72 73 67 55 56 53 39 40 39 26 28 27 39 40 39 +68 70 65 51 52 50 39 40 39 28 31 30 22 24 23 17 20 20 +14 17 17 12 14 14 10 13 13 9 11 11 9 11 11 9 11 11 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +27 29 28 40 41 39 46 47 45 51 52 50 55 57 54 63 64 60 +131 127 93 197 193 154 210 208 158 197 193 154 168 163 120 96 95 69 +47 48 46 40 41 39 32 34 33 71 71 57 145 141 105 184 179 149 +184 179 149 131 127 93 13 13 13 12 12 12 12 12 12 48 49 45 +168 163 120 184 179 149 156 151 111 6 7 7 14 14 13 177 172 135 +239 239 170 40 41 39 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 3 3 3 6 7 7 11 11 11 16 16 16 +18 19 18 21 22 21 23 24 24 27 29 28 32 34 33 37 39 37 +41 42 42 43 45 43 47 48 46 51 52 50 51 52 50 51 52 50 +51 52 50 49 51 48 46 47 45 40 41 39 32 34 33 25 27 26 +20 20 20 14 14 13 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 33 36 34 197 193 154 184 179 149 +41 42 42 0 0 0 0 0 0 0 0 0 3 3 3 184 179 149 +251 251 187 251 251 187 184 179 149 48 49 45 0 0 0 0 0 0 +16 17 12 121 119 87 177 172 135 194 189 146 188 184 146 145 141 105 +82 81 62 63 64 60 46 47 45 31 33 31 21 22 21 35 37 36 +68 70 65 51 52 50 37 39 37 27 30 29 22 24 23 17 20 20 +13 16 16 12 14 14 10 13 13 9 11 11 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 25 27 26 +38 39 37 43 45 43 51 52 50 55 56 53 60 60 56 63 64 60 +92 91 72 158 153 112 176 171 126 171 165 117 149 143 98 82 81 62 +44 46 43 38 39 37 30 32 31 71 71 57 131 127 93 160 154 106 +149 143 98 82 81 62 13 13 13 12 12 12 12 12 12 46 47 43 +121 119 87 134 131 96 96 95 69 7 7 6 38 39 37 131 127 93 +145 141 105 12 13 12 0 0 0 1 1 1 3 3 3 6 7 7 +10 10 9 12 12 12 14 14 13 16 16 16 18 19 18 21 22 21 +22 24 23 26 28 27 30 31 28 33 36 34 37 39 37 40 41 39 +41 42 42 43 45 43 46 47 45 46 47 45 46 47 45 43 45 43 +41 42 42 37 39 37 31 33 31 26 28 27 21 22 21 16 16 16 +6 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 177 172 135 251 251 187 +197 193 154 27 29 28 0 0 0 0 0 0 0 0 0 110 109 94 +239 239 170 239 239 170 184 179 149 87 86 72 2 2 1 0 0 0 +1 1 1 82 81 62 142 137 94 165 161 109 165 161 109 131 127 93 +75 75 61 55 56 53 37 39 37 25 27 26 19 20 19 32 34 33 +65 66 61 49 51 48 35 37 36 27 29 28 20 23 23 16 19 19 +13 16 16 13 13 13 10 12 12 9 11 11 8 10 10 8 10 10 +8 9 9 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 22 24 23 35 37 36 +41 42 42 47 48 46 55 56 53 58 59 55 63 64 60 65 66 61 +71 71 57 131 127 93 160 154 106 160 154 106 142 137 94 82 81 62 +46 47 43 40 41 39 33 36 34 66 65 55 125 122 87 149 143 98 +142 137 94 82 81 62 17 17 17 18 19 17 14 14 13 46 47 43 +118 116 76 125 122 87 96 95 69 16 17 12 71 71 57 103 101 77 +82 81 62 11 11 11 11 11 11 13 13 13 14 14 13 14 14 13 +15 15 15 16 16 16 17 17 17 19 20 19 21 22 21 23 24 24 +26 28 27 27 29 28 31 33 31 33 36 34 35 37 36 38 39 37 +39 40 39 39 40 39 38 39 37 37 39 37 35 37 36 31 33 31 +27 29 28 24 26 24 21 22 21 17 17 17 12 12 12 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 68 70 65 251 251 187 +251 251 187 156 151 111 2 2 1 0 0 0 0 0 0 43 44 41 +177 172 135 184 179 149 158 153 112 103 101 77 19 20 18 0 0 0 +0 0 0 46 47 43 131 127 93 160 154 106 160 154 106 131 127 93 +71 71 57 43 45 43 30 32 31 21 22 21 16 16 16 26 28 27 +63 64 60 47 48 46 35 37 36 26 28 27 20 23 23 16 19 19 +13 16 16 13 13 13 10 12 12 9 11 11 8 10 10 8 10 10 +7 9 9 7 9 9 8 9 9 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 20 20 20 33 36 34 40 41 39 +46 47 45 51 52 50 55 57 54 60 60 56 63 64 60 65 66 61 +66 65 55 118 116 76 151 147 98 165 161 109 151 147 98 121 119 87 +96 95 69 96 95 69 96 95 69 103 101 77 142 137 94 151 147 98 +142 137 94 103 101 77 82 81 62 82 81 62 82 81 62 96 95 69 +131 127 93 142 137 94 103 101 77 46 47 43 96 95 69 118 116 76 +71 71 57 14 14 13 14 14 13 15 15 15 15 15 15 16 16 16 +16 16 16 17 17 17 18 19 18 20 20 20 21 22 21 23 24 24 +25 27 26 27 29 28 30 31 28 30 32 31 31 33 31 31 33 31 +31 33 31 31 33 31 30 31 28 27 29 28 25 27 26 22 24 23 +20 20 20 16 16 16 13 13 13 6 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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +58 59 55 68 70 65 8 8 7 0 0 0 10 10 9 210 208 158 +251 251 187 184 179 149 38 39 37 0 0 0 0 0 0 8 8 7 +103 101 77 149 143 98 149 143 98 118 116 76 40 41 39 25 27 25 +53 55 47 82 81 62 144 139 99 165 161 109 165 161 109 142 137 94 +71 71 57 35 37 36 24 26 24 18 19 18 15 15 15 22 24 23 +63 64 60 46 47 45 33 36 34 26 28 27 20 23 22 17 18 17 +12 15 15 11 13 13 10 12 12 9 11 11 8 10 10 8 10 10 +7 9 9 7 9 9 7 9 9 7 9 9 8 9 9 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 16 16 16 30 31 28 35 37 36 41 42 42 +47 48 46 55 56 53 58 59 55 63 64 60 65 66 61 65 66 61 +61 61 53 103 101 77 151 147 98 171 165 117 171 165 117 168 163 120 +158 153 112 158 153 112 155 149 109 151 147 98 151 147 98 160 154 106 +151 147 98 149 143 98 142 137 94 149 143 98 149 143 98 149 143 98 +155 149 109 151 147 98 131 127 93 103 101 77 125 122 87 118 116 76 +71 71 57 16 16 16 16 16 16 16 16 16 17 17 17 17 17 17 +17 17 17 17 17 17 18 19 18 19 20 19 20 20 20 21 22 21 +23 24 24 24 26 24 25 27 26 26 28 27 26 28 27 26 28 27 +25 27 26 24 26 24 22 24 23 21 22 21 19 20 19 16 16 16 +14 14 13 8 8 7 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 +20 20 20 184 179 149 168 163 120 21 22 21 0 0 0 105 104 92 +177 172 135 145 141 105 71 71 57 0 0 0 0 0 0 0 0 0 +66 65 55 131 127 93 151 147 98 142 137 94 118 116 76 121 119 87 +145 141 105 158 153 112 176 171 126 178 174 128 176 171 126 149 145 103 +96 95 69 31 33 31 21 22 21 16 16 16 14 14 13 18 19 18 +60 60 56 46 47 45 33 36 34 25 27 26 21 22 21 15 18 18 +12 15 15 11 13 13 9 11 11 8 10 10 8 10 10 8 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 8 9 9 +8 9 9 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 10 12 12 26 28 27 31 33 31 38 39 37 43 45 43 +51 52 50 55 56 53 60 60 56 63 64 60 65 66 61 68 70 65 +63 64 60 96 95 69 158 153 112 178 174 128 188 184 146 194 189 146 +194 189 146 188 184 146 184 181 136 176 171 126 171 165 117 173 167 111 +173 167 111 165 161 109 171 165 117 174 170 121 176 171 126 178 174 128 +178 174 128 174 170 121 160 154 106 149 143 98 149 143 98 125 122 87 +71 71 57 16 16 16 16 16 16 17 17 17 17 17 17 17 17 17 +17 17 17 17 17 17 17 17 17 18 19 18 19 20 19 20 20 20 +21 22 21 21 22 21 21 22 21 22 24 23 21 22 21 21 22 21 +21 22 21 19 20 19 18 19 18 16 16 16 14 14 13 11 11 11 +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 105 104 92 197 193 154 110 109 94 9 9 8 36 38 35 +121 119 87 131 127 93 96 95 69 18 19 17 30 31 28 66 65 55 +96 95 69 142 137 94 160 154 106 160 154 106 160 154 106 168 163 120 +184 181 136 194 191 148 197 193 154 197 193 154 194 189 146 168 163 120 +125 122 87 46 47 43 18 19 18 15 15 15 13 13 13 14 14 13 +55 57 54 43 45 43 32 34 33 25 27 26 18 22 22 17 17 17 +12 14 14 10 12 12 9 11 11 8 10 10 8 9 9 7 9 9 +6 8 8 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 +7 9 9 8 9 9 8 9 9 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 32 34 33 41 42 42 35 37 36 39 40 39 37 39 37 +35 37 36 55 57 54 60 60 56 63 64 60 65 66 61 65 66 61 +61 63 57 115 113 82 168 163 120 194 191 148 204 201 155 210 208 158 +210 208 158 210 208 158 197 193 154 194 189 146 186 182 128 176 171 126 +174 170 121 176 171 126 186 182 128 190 186 136 194 191 148 197 193 154 +197 193 154 188 184 146 181 176 137 174 170 121 165 161 109 142 137 94 +82 81 62 24 26 24 16 16 16 16 16 16 16 16 16 16 16 16 +17 17 17 17 17 17 17 17 17 17 17 17 18 19 18 19 20 19 +19 20 19 19 20 19 20 20 20 19 20 19 19 20 19 18 19 18 +17 17 17 15 15 15 13 13 13 12 12 12 6 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +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 17 137 133 100 115 113 82 53 55 47 19 20 18 +103 101 77 144 139 99 137 133 100 115 113 82 137 133 100 156 151 111 +158 153 112 164 159 111 171 165 117 174 170 121 178 174 128 194 189 146 +204 201 155 214 212 158 214 212 158 214 212 158 210 208 158 188 184 146 +158 153 112 87 86 72 17 17 17 13 13 13 13 13 13 15 15 15 +55 56 53 43 45 43 32 34 33 24 26 24 17 20 20 16 16 16 +12 14 14 10 12 12 8 10 10 8 10 10 7 9 9 6 8 8 +6 8 8 6 8 8 6 8 8 7 9 9 7 9 9 7 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 8 9 9 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 110 109 94 84 83 72 49 51 48 26 28 27 8 10 10 +8 9 9 51 52 50 58 59 55 63 64 60 63 64 60 63 64 60 +66 65 55 134 131 96 181 176 137 210 208 158 214 212 158 239 239 170 +239 239 170 224 223 159 210 208 158 204 201 155 194 189 146 186 182 128 +186 182 128 184 181 136 194 189 146 204 201 155 210 208 158 210 208 158 +210 208 158 210 208 158 197 193 154 190 186 136 176 171 126 155 149 109 +118 116 76 36 38 35 15 15 15 16 16 16 16 16 16 16 16 16 +16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 17 17 17 +17 17 17 17 17 17 17 17 17 16 16 16 16 16 16 15 15 15 +13 13 13 12 12 12 8 8 7 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 53 55 47 103 101 77 96 95 69 53 55 47 +103 101 77 158 153 112 177 172 135 184 179 149 188 184 146 197 193 154 +194 189 146 190 186 136 184 181 136 184 181 136 194 189 146 210 208 158 +214 212 158 239 239 170 251 251 187 251 251 187 224 223 159 204 201 155 +177 172 135 121 119 87 30 31 28 13 13 13 12 12 12 39 40 39 +60 60 56 43 45 43 32 34 33 23 25 24 18 19 18 13 16 16 +13 13 13 9 11 11 8 10 10 8 9 9 6 8 8 6 8 8 +6 8 8 6 8 8 6 8 8 6 8 8 6 8 8 7 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 +7 9 9 8 9 9 8 9 9 8 10 10 8 10 10 8 10 10 +14 17 17 197 193 154 158 153 112 55 57 54 7 9 9 7 9 9 +8 10 10 51 52 50 58 59 55 60 60 56 63 64 60 63 64 60 +71 71 57 155 149 109 194 191 148 214 212 158 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 210 208 158 197 193 154 190 186 136 +190 186 136 194 189 146 204 201 155 210 208 158 224 223 159 239 239 170 +239 239 170 224 223 159 210 208 158 204 201 155 190 186 136 164 159 111 +125 122 87 40 41 39 15 15 15 15 15 15 15 15 15 15 15 15 +16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 +16 16 16 16 16 16 15 15 15 14 14 13 13 13 13 12 12 12 +8 9 9 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 21 22 20 96 95 69 125 122 87 121 119 87 +144 139 99 177 172 135 197 193 154 210 208 158 214 212 158 214 212 158 +210 208 158 204 201 155 194 191 148 194 189 146 204 201 155 214 212 158 +239 239 170 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158 +188 184 146 145 141 105 53 55 47 12 12 12 15 15 15 63 64 60 +63 64 60 41 42 42 31 33 31 23 24 24 17 18 17 12 15 15 +11 13 13 9 11 11 8 9 9 7 9 9 6 8 8 6 8 8 +6 7 7 6 7 7 6 8 8 6 8 8 6 8 8 6 8 8 +6 8 8 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 8 8 7 +43 45 43 251 251 187 156 151 111 8 10 10 7 9 9 7 9 9 +21 22 21 51 52 50 55 56 53 55 57 54 58 59 55 58 59 55 +75 75 61 158 153 112 197 193 154 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 214 212 158 204 201 155 194 189 146 +190 186 136 197 193 154 210 208 158 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 210 208 158 197 193 154 176 171 126 +125 122 87 36 38 35 14 14 13 14 14 13 15 15 15 15 15 15 +15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 +15 15 15 14 14 13 13 13 13 12 12 12 10 10 9 3 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 7 7 5 71 71 57 131 127 93 158 153 112 +177 172 135 197 193 154 214 212 158 239 239 170 251 251 187 251 251 187 +238 237 168 210 208 158 204 201 155 197 193 154 204 201 155 214 212 158 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158 +197 193 154 156 151 111 66 65 55 12 12 12 37 39 37 58 59 55 +58 59 55 41 42 42 31 33 31 22 24 23 17 17 17 12 14 14 +10 12 12 8 10 10 6 8 8 6 8 8 6 7 7 6 7 7 +6 7 7 5 7 7 6 7 7 6 7 7 6 8 8 6 8 8 +6 8 8 6 8 8 6 8 8 7 9 9 7 9 9 7 9 9 +7 9 9 6 8 8 6 8 8 6 8 8 6 8 8 6 8 8 +61 63 57 197 193 154 16 19 19 6 8 8 6 8 8 8 9 9 +41 42 42 47 48 46 51 52 50 51 52 50 55 56 53 55 56 53 +71 71 57 158 153 112 197 193 154 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 214 212 158 204 201 155 194 189 146 +190 186 136 197 193 154 210 208 158 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 224 223 159 204 201 155 177 172 135 +121 119 87 30 31 28 13 13 13 14 14 13 14 14 13 14 14 13 +14 14 13 14 14 13 15 15 15 15 15 15 14 14 13 13 13 13 +12 12 12 12 12 12 10 10 9 4 5 5 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 48 49 45 131 127 93 174 170 121 +194 189 146 210 208 158 239 239 170 251 251 187 251 251 187 251 251 187 +251 251 187 214 212 158 204 201 155 197 193 154 204 201 155 210 208 158 +239 239 170 251 251 187 251 251 187 251 251 187 239 239 170 214 212 158 +194 191 148 156 151 111 71 71 57 19 20 19 51 52 50 51 52 50 +51 52 50 41 42 42 30 32 31 21 22 21 17 17 17 13 13 13 +9 11 11 8 9 9 6 8 8 6 7 7 6 7 7 5 7 7 +5 6 5 5 6 5 5 7 7 5 7 7 6 7 7 6 7 7 +6 8 8 6 8 8 6 8 8 6 7 7 6 7 7 6 7 7 +6 7 7 6 8 8 6 8 8 6 8 8 6 8 8 6 8 8 +55 56 53 43 45 43 6 8 8 6 8 8 6 8 8 47 48 46 +60 60 56 47 48 46 46 47 45 47 48 46 38 39 37 10 12 12 +66 65 55 145 141 105 197 193 154 214 212 158 251 251 187 251 251 187 +251 251 187 251 251 187 224 223 159 210 208 158 194 191 148 184 181 136 +184 181 136 194 189 146 204 201 155 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 181 176 137 +115 113 82 21 22 20 13 13 13 13 13 13 13 13 13 13 13 13 +14 14 13 13 13 13 13 13 13 13 13 13 12 12 12 11 11 11 +10 10 9 6 7 7 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 2 2 1 66 65 55 144 139 99 178 174 128 +204 201 155 214 212 158 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 214 212 158 204 201 155 194 191 148 197 193 154 204 201 155 +214 212 158 239 239 170 239 239 170 239 239 170 214 212 158 210 208 158 +184 181 136 149 145 103 66 65 55 41 42 42 47 48 46 46 47 45 +43 45 43 39 40 39 28 31 30 21 22 21 16 16 16 10 12 12 +8 10 10 6 8 8 6 7 7 6 7 7 5 6 5 5 6 5 +5 6 5 5 6 5 5 6 5 5 6 5 5 7 7 5 7 7 +6 7 7 6 7 7 6 7 7 5 7 7 5 7 7 5 7 7 +5 7 7 6 7 7 6 7 7 6 7 7 6 7 7 6 8 8 +6 8 8 6 8 8 6 7 7 6 7 7 46 47 45 156 151 111 +105 104 92 58 59 55 43 45 43 32 34 33 6 8 8 6 8 8 +49 51 48 125 122 87 181 176 137 204 201 155 214 212 158 239 239 170 +239 239 170 214 212 158 210 208 158 197 193 154 181 176 137 176 171 126 +176 171 126 184 181 136 197 193 154 210 208 158 239 239 170 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 177 172 135 +99 98 80 13 13 13 12 12 12 12 12 12 13 13 13 12 12 12 +12 12 12 12 12 12 11 11 11 11 11 11 8 9 9 4 5 5 +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 1 1 0 61 61 53 142 137 94 181 176 137 +204 201 155 224 223 159 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 214 212 158 197 193 154 190 186 136 184 181 136 188 184 146 +197 193 154 204 201 155 210 208 158 210 208 158 204 201 155 194 189 146 +176 171 126 134 131 96 66 65 55 43 45 43 41 42 42 39 40 39 +35 37 36 33 36 34 27 29 28 20 20 20 15 15 15 9 11 11 +8 9 9 6 7 7 5 6 5 5 6 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 5 6 5 4 5 5 +4 5 5 5 6 5 4 5 5 5 6 5 5 6 5 5 6 5 +5 7 7 5 7 7 5 7 7 5 7 7 5 7 7 5 7 7 +6 7 7 6 7 7 6 7 7 28 31 30 184 179 149 184 179 149 +145 141 105 84 83 72 27 29 28 5 7 7 5 6 5 16 16 16 +43 44 41 96 95 69 158 153 112 188 184 146 204 201 155 210 208 158 +204 201 155 197 193 154 184 179 149 177 172 135 168 163 120 164 159 111 +164 159 111 174 170 121 184 181 136 197 193 154 214 212 158 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 177 172 135 +71 71 57 11 11 11 12 12 12 11 11 11 11 11 11 11 11 11 +10 10 9 10 10 9 8 8 7 3 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 31 33 31 121 119 87 176 171 126 +197 193 154 214 212 158 251 251 187 251 251 187 251 251 187 251 251 187 +239 239 170 210 208 158 194 189 146 178 174 128 174 170 121 176 171 126 +177 172 135 181 176 137 184 179 149 184 179 149 181 176 137 178 174 128 +158 153 112 121 119 87 53 55 47 37 39 37 33 36 34 30 32 31 +27 29 28 25 27 26 24 26 24 19 20 19 13 13 13 8 10 10 +6 8 8 6 7 7 5 6 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 3 4 4 3 4 4 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +5 6 5 5 6 5 5 6 5 5 6 5 5 6 5 5 6 5 +5 6 5 5 6 5 12 14 14 145 141 105 184 179 149 177 172 135 +90 89 73 21 22 21 5 6 5 5 6 5 4 5 5 37 39 37 +38 39 37 61 61 53 134 131 96 168 163 120 184 181 136 188 184 146 +184 179 149 177 172 135 168 163 120 164 159 111 155 149 109 151 147 98 +151 147 98 164 159 111 176 171 126 184 179 149 210 208 158 239 239 170 +251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 158 153 112 +46 47 43 10 10 9 10 10 9 10 10 9 8 9 9 8 9 9 +6 7 7 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 13 12 7 82 81 62 158 153 112 +188 184 146 210 208 158 239 239 170 251 251 187 251 251 187 251 251 187 +224 223 159 204 201 155 184 181 136 171 165 117 164 159 111 160 154 106 +158 153 112 164 159 111 168 163 120 168 163 120 168 163 120 164 159 111 +142 137 94 96 95 69 43 44 41 27 29 28 26 28 27 23 24 24 +21 22 21 18 19 18 17 17 17 18 19 18 13 13 13 8 8 7 +6 7 7 5 6 5 4 5 5 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 3 3 3 3 3 3 4 4 3 4 4 +3 4 4 3 4 4 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 31 33 31 65 66 61 +37 39 37 38 39 37 96 95 69 144 139 99 168 163 120 174 170 121 +168 163 120 164 159 111 155 149 109 149 145 103 149 143 98 142 137 94 +149 143 98 151 147 98 164 159 111 177 172 135 197 193 154 210 208 158 +251 251 187 251 251 187 251 251 187 239 239 170 197 193 154 137 133 100 +24 26 24 8 9 9 8 9 9 8 8 7 6 7 7 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 46 47 43 125 122 87 +176 171 126 197 193 154 210 208 158 239 239 170 251 251 187 239 239 170 +214 212 158 197 193 154 181 176 137 164 159 111 151 147 98 149 143 98 +149 143 98 149 143 98 149 145 103 155 149 109 160 154 106 149 143 98 +118 116 76 82 81 62 30 31 28 21 22 21 19 20 19 17 17 17 +14 14 13 12 12 12 10 10 9 12 12 12 10 12 12 6 8 8 +4 5 5 3 4 4 3 4 4 3 4 4 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 2 3 3 2 3 3 +3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 4 5 5 +4 5 5 3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 3 4 4 3 4 4 23 24 24 110 109 94 72 73 67 +39 40 39 22 24 23 46 47 43 103 101 77 142 137 94 155 149 109 +160 154 106 155 149 109 149 143 98 142 137 94 142 137 94 142 137 94 +142 137 94 149 143 98 155 149 109 176 171 126 184 179 149 210 208 158 +239 239 170 251 251 187 251 251 187 214 212 158 184 179 149 105 104 92 +10 10 9 6 7 7 3 4 4 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 12 12 9 82 81 62 +149 145 103 181 176 137 197 193 154 210 208 158 214 212 158 214 212 158 +210 208 158 197 193 154 177 172 135 158 153 112 149 143 98 142 137 94 +142 137 94 142 137 94 149 143 98 151 147 98 151 147 98 131 127 93 +103 101 77 71 71 57 22 24 23 15 15 15 13 13 13 11 11 11 +8 9 9 6 7 7 6 7 7 4 5 5 8 9 9 6 7 7 +4 5 5 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 +2 3 3 2 3 3 2 3 3 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 3 3 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 21 22 21 145 141 105 145 141 105 72 73 67 +17 18 17 3 4 4 21 22 20 66 65 55 118 116 76 142 137 94 +149 143 98 151 147 98 149 143 98 142 137 94 142 137 94 142 137 94 +142 137 94 149 143 98 155 149 109 168 163 120 184 179 149 210 208 158 +239 239 170 251 251 187 251 251 187 210 208 158 177 172 135 71 71 57 +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 36 38 35 +115 113 82 158 153 112 181 176 137 197 193 154 204 201 155 210 208 158 +204 201 155 188 184 146 177 172 135 164 159 111 149 145 103 142 137 94 +142 137 94 142 137 94 149 143 98 151 147 98 149 143 98 125 122 87 +96 95 69 61 61 53 16 17 12 8 9 9 8 8 7 6 7 7 +4 5 5 3 4 4 3 3 3 3 3 3 3 3 3 5 6 5 +3 4 4 2 3 3 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 +2 2 2 2 2 2 2 3 3 2 3 3 2 3 3 2 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 2 3 3 2 3 3 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 4 4 8 9 9 8 8 7 3 3 3 +3 3 3 3 3 3 9 9 8 36 38 35 82 81 62 118 116 76 +142 137 94 151 147 98 151 147 98 151 147 98 149 143 98 149 143 98 +149 143 98 151 147 98 160 154 106 176 171 126 188 184 146 210 208 158 +239 239 170 251 251 187 239 239 170 210 208 158 156 151 111 31 33 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 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 5 +66 65 55 125 122 87 158 153 112 181 176 137 194 189 146 197 193 154 +197 193 154 184 179 149 177 172 135 168 163 120 156 151 111 151 147 98 +151 147 98 151 147 98 151 147 98 161 156 96 149 143 98 118 116 76 +82 81 62 53 55 47 12 12 9 4 5 5 3 4 4 3 3 3 +3 3 3 3 3 3 2 2 2 2 2 2 1 1 1 1 2 2 +3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 2 2 +1 2 2 1 2 2 1 2 2 2 2 2 2 2 2 2 3 3 +2 3 3 2 3 3 2 3 3 2 3 3 2 2 2 2 2 2 +2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 +2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 3 3 3 +3 3 3 3 3 3 72 73 67 61 61 53 53 55 47 96 95 69 +131 127 93 151 147 98 161 156 96 161 156 96 151 147 98 151 147 98 +161 156 96 160 154 106 164 159 111 177 172 135 197 193 154 210 208 158 +239 239 170 251 251 187 224 223 159 197 193 154 131 127 93 9 9 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +24 26 24 82 81 62 131 127 93 164 159 111 178 174 128 188 184 146 +188 184 146 188 184 146 181 176 137 176 171 126 168 163 120 164 159 111 +160 154 106 160 154 106 160 154 106 160 154 106 151 147 98 125 122 87 +82 81 62 61 61 53 12 12 9 3 3 3 3 3 3 2 2 2 +2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 2 2 1 2 2 1 2 2 1 2 2 +1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 +2 3 3 30 32 31 72 73 67 31 33 31 36 38 35 82 81 62 +118 116 76 149 143 98 161 156 96 161 156 96 161 156 96 160 154 106 +165 161 109 165 161 109 176 171 126 188 184 146 204 201 155 214 212 158 +239 239 170 239 239 170 214 212 158 184 179 149 82 81 62 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 43 44 41 96 95 69 131 127 93 160 154 106 176 171 126 +184 181 136 184 181 136 184 181 136 181 176 137 178 174 128 174 170 121 +171 165 117 173 167 111 173 167 111 173 167 111 160 154 106 131 127 93 +96 95 69 66 65 55 16 17 12 2 2 2 1 1 1 1 1 1 +1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 10 9 6 30 31 28 71 71 57 +118 116 76 149 143 98 165 161 109 165 161 109 165 161 109 173 167 111 +173 167 111 176 171 126 184 181 136 197 193 154 210 208 158 224 223 159 +251 251 187 239 239 170 210 208 158 168 163 120 40 41 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 0 0 0 0 0 0 +0 0 0 13 12 7 61 61 53 96 95 69 131 127 93 160 154 106 +176 171 126 184 181 136 184 181 136 188 184 146 184 181 136 184 181 136 +184 181 136 186 182 128 186 182 128 178 174 128 174 170 121 149 145 103 +118 116 76 82 81 62 21 22 20 1 1 1 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 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 +1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 3 3 3 30 31 28 66 65 55 +118 116 76 149 143 98 165 161 109 173 167 111 173 167 111 174 170 121 +186 182 128 190 186 136 197 193 154 210 208 158 224 223 159 251 251 187 +251 251 187 239 239 170 197 193 154 137 133 100 12 12 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 30 31 28 71 71 57 103 101 77 134 131 96 +164 159 111 176 171 126 184 181 136 188 184 146 194 189 146 197 193 154 +197 193 154 197 193 154 194 191 148 194 189 146 190 186 136 176 171 126 +145 141 105 103 101 77 40 41 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 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 2 2 +1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 +1 2 2 1 2 2 1 2 2 1 2 2 30 31 28 71 71 57 +118 116 76 160 154 106 173 167 111 178 174 128 186 182 128 190 186 136 +194 191 148 204 201 155 210 208 158 224 223 159 251 251 187 251 251 187 +251 251 187 214 212 158 184 179 149 84 83 72 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 5 5 3 43 44 41 82 81 62 103 101 77 +142 137 94 165 161 109 178 174 128 190 186 136 197 193 154 204 201 155 +210 208 158 210 208 158 210 208 158 210 208 158 210 208 158 197 193 154 +177 172 135 145 141 105 79 78 62 5 4 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 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 2 2 1 2 2 30 31 28 82 81 62 +142 137 94 165 161 109 178 174 128 190 186 136 194 191 148 204 201 155 +210 208 158 214 212 158 239 239 170 251 251 187 251 251 187 251 251 187 +251 251 187 210 208 158 168 163 120 36 38 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 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 17 12 53 55 47 82 81 62 +118 116 76 151 147 98 171 165 117 184 181 136 194 191 148 210 208 158 +214 212 158 224 223 159 239 239 170 239 239 170 224 223 159 214 212 158 +197 193 154 176 171 126 115 113 82 24 26 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 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 40 41 39 103 101 77 +151 147 98 176 171 126 190 186 136 197 193 154 210 208 158 214 212 158 +239 239 170 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +239 239 170 197 193 154 110 109 94 3 4 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 30 31 28 66 65 55 +96 95 69 125 122 87 160 154 106 178 174 128 194 189 146 204 201 155 +214 212 158 239 239 170 251 251 187 251 251 187 251 251 187 239 239 170 +210 208 158 188 184 146 149 145 103 61 61 53 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 61 61 53 131 127 93 +164 159 111 184 181 136 197 193 154 210 208 158 224 223 159 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +210 208 158 168 163 120 43 44 41 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 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 3 2 36 38 35 +71 71 57 96 95 69 142 137 94 165 161 109 184 181 136 197 193 154 +210 208 158 239 239 170 251 251 187 251 251 187 251 251 187 251 251 187 +214 212 158 197 193 154 168 163 120 103 101 77 7 7 5 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 0 0 0 0 0 0 0 0 0 82 81 62 142 137 94 +174 170 121 194 189 146 210 208 158 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 224 223 159 +184 179 149 99 98 80 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 7 7 5 +43 44 41 82 81 62 118 116 76 142 137 94 171 165 117 190 186 136 +204 201 155 224 223 159 251 251 187 251 251 187 251 251 187 251 251 187 +214 212 158 197 193 154 174 170 121 125 122 87 30 31 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 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 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 3 4 3 82 81 62 149 143 98 +176 171 126 194 191 148 210 208 158 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 239 239 170 204 201 155 +145 141 105 30 31 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 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 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 9 6 46 47 43 82 81 62 118 116 76 149 143 98 174 170 121 +194 189 146 210 208 158 224 223 159 251 251 187 251 251 187 224 223 159 +210 208 158 194 191 148 174 170 121 134 131 96 53 55 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 5 96 95 69 149 143 98 +176 171 126 194 191 148 210 208 158 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 177 172 135 +75 75 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 9 6 46 47 43 82 81 62 118 116 76 149 143 98 +176 171 126 194 191 148 210 208 158 214 212 158 214 212 158 210 208 158 +197 193 154 184 181 136 164 159 111 131 127 93 53 55 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 5 96 95 69 149 143 98 +174 170 121 194 189 146 204 201 155 214 212 158 239 239 170 251 251 187 +251 251 187 251 251 187 239 239 170 210 208 158 184 179 149 110 109 94 +12 12 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 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +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 9 6 43 44 41 82 81 62 115 113 82 +144 139 99 168 163 120 188 184 146 197 193 154 197 193 154 194 189 146 +184 181 136 174 170 121 151 147 98 118 116 76 36 38 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 3 2 82 81 62 142 137 94 +171 165 117 186 182 128 194 191 148 210 208 158 214 212 158 224 223 159 +239 239 170 224 223 159 210 208 158 184 179 149 137 133 100 36 38 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 5 36 38 35 71 71 57 +103 101 77 131 127 93 155 149 109 168 163 120 168 163 120 168 163 120 +164 159 111 149 143 98 125 122 87 82 81 62 13 12 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 61 61 53 125 122 87 +160 154 106 174 170 121 184 181 136 194 189 146 204 201 155 210 208 158 +210 208 158 204 201 155 184 179 149 145 141 105 61 61 53 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 2 30 31 28 +61 61 53 82 81 62 103 101 77 121 119 87 125 122 87 125 122 87 +118 116 76 103 101 77 79 78 62 24 26 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 25 27 25 96 95 69 +142 137 94 160 154 106 171 165 117 178 174 128 184 181 136 184 181 136 +181 176 137 177 172 135 145 141 105 75 75 61 5 5 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 0 0 0 0 0 0 0 0 0 +16 17 12 40 41 39 61 61 53 71 71 57 71 71 57 71 71 57 +66 65 55 43 44 41 12 12 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 1 1 1 46 47 43 +96 95 69 125 122 87 142 137 94 149 145 103 155 149 109 155 149 109 +145 141 105 121 119 87 66 65 55 7 7 5 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 16 17 12 24 26 24 25 27 25 19 20 18 +7 7 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 1 +25 27 25 61 61 53 82 81 62 96 95 69 96 95 69 82 81 62 +61 61 53 25 27 25 2 2 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 5 6 5 13 12 7 10 9 6 3 4 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 diff --git a/drivers/video/logo/logo_linux_vga16.ppm b/drivers/video/logo/logo_linux_vga16.ppm index 1850c15e6feb..12ac3a5454c0 100644 --- a/drivers/video/logo/logo_linux_vga16.ppm +++ b/drivers/video/logo/logo_linux_vga16.ppm @@ -1,1604 +1,2739 @@ P3 -# Standard 16-color Linux logo -80 80 +142 114 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 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 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 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 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 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 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 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 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 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 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 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 0 0 0 0 0 0 0 0 0 - 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 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 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 - 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 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 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 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 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 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 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 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 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 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 170 170 170 170 170 170 170 170 170 - 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 - 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 85 85 85 -170 170 170 170 170 170 255 255 255 255 255 255 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 255 255 255 170 170 170 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 - 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 85 85 85 -170 170 170 0 0 0 0 0 0 255 255 255 - 85 85 85 0 0 0 0 0 0 0 0 0 -255 255 255 170 170 170 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 - 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 85 85 85 - 85 85 85 0 0 0 0 0 0 170 170 170 - 85 85 85 0 0 0 0 0 0 0 0 0 -255 255 255 85 85 85 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 - 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 85 85 85 -170 170 170 0 0 0 0 0 0 170 170 170 - 85 85 85 85 85 85 85 85 85 85 85 85 -255 255 255 85 85 85 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 - 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 -255 255 255 0 0 0 0 0 0 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 85 85 85 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 - 0 0 0 85 85 85 0 0 0 0 0 0 -170 170 170 170 170 170 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 170 170 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 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 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 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 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 85 85 85 85 85 85 0 0 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 170 85 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 85 85 85 85 85 85 0 0 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 170 85 0 85 85 85 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 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 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 - 85 85 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 85 85 85 0 0 0 - 0 0 0 85 85 85 170 170 170 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 85 85 85 0 0 0 - 85 85 85 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 170 170 170 170 170 170 170 170 0 0 0 - 0 0 0 0 0 0 170 170 170 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 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 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 170 170 170 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 85 85 85 - 0 0 0 0 0 0 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 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 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 170 170 170 170 170 170 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 170 170 170 170 170 170 170 170 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 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 - 85 85 85 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 170 170 170 170 170 170 -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 - 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 -170 170 170 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 0 0 0 85 85 85 - 0 0 0 0 0 0 85 85 85 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 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 0 0 0 85 85 85 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 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 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 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 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 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 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 85 85 85 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 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 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 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 - 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 -255 255 255 255 255 255 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 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 0 0 0 - 85 85 85 170 170 170 170 170 170 170 170 170 -255 255 255 255 255 255 255 255 255 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 -170 170 170 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 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 0 0 0 -170 170 170 170 170 170 170 170 170 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 255 255 255 -255 255 255 255 255 255 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 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 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 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 - 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 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 - 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 170 170 170 170 170 170 - 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 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 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 255 255 255 255 255 255 -170 170 170 85 85 85 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 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 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 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 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 85 85 85 - 85 85 85 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 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 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 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 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 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 - 85 85 85 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 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 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 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 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 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 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 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 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 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 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 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 - 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 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 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 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 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 -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 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 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 85 85 85 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 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 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 85 85 85 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 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 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 85 85 85 0 0 0 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 -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 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 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 85 85 85 0 0 0 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 -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 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 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 85 85 85 0 0 0 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 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 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 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 255 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 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 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 - 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 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 170 85 0 -255 255 85 170 85 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 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 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 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 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 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 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 -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 255 255 255 255 255 255 255 255 255 -255 255 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 170 85 0 255 255 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 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 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 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 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 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 -170 85 0 255 255 85 170 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 -170 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 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 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 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 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 85 0 -255 255 85 170 85 0 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 170 85 0 -255 255 85 170 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 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 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 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 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 -170 85 0 255 255 85 170 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 255 255 85 -170 85 0 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 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 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 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 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 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 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 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 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 255 255 255 255 255 255 255 255 255 -255 255 255 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 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 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 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 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 255 255 255 255 255 255 -255 255 255 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 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 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 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 - 0 0 0 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 170 170 170 170 170 170 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 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 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 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 170 170 170 170 170 170 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -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 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 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 255 255 255 -255 255 255 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 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 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 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 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 255 255 255 255 255 255 255 255 255 -170 170 170 85 85 85 85 85 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 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 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 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 170 170 170 - 85 85 85 0 0 0 0 0 0 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 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 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 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 170 170 170 85 85 85 - 0 0 0 0 0 0 0 0 0 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 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 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 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 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 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 - 0 0 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 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 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -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 0 0 0 - 0 0 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 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 85 85 85 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 170 85 0 170 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 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 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 85 85 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 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 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 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 85 85 85 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 170 85 0 170 85 0 170 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 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 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 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 170 85 0 -170 85 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 170 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 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 170 85 0 170 85 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 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 170 85 0 -170 85 0 170 85 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 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 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 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 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 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 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 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 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 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 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +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 +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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 0 0 0 85 85 85 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 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 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 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 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 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 +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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 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 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 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 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +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 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 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 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 85 85 85 +0 0 0 85 85 85 170 170 170 170 85 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 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 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 +170 170 170 255 255 85 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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 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 85 85 85 0 0 0 85 85 85 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 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 170 170 170 +255 255 85 170 170 170 170 170 170 170 85 0 85 255 85 170 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 0 0 0 0 +0 0 0 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 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 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +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 +85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 170 85 0 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 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 85 85 85 85 85 85 170 85 0 170 170 170 +170 170 170 170 85 0 170 170 170 170 170 170 170 85 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 0 0 0 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 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 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 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 255 85 +255 85 85 85 255 85 170 170 170 170 85 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 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 85 85 85 85 85 85 85 85 85 85 85 85 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 85 85 85 170 85 0 85 85 85 85 85 85 +170 170 170 170 85 0 170 170 170 85 85 85 170 85 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 0 0 0 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 85 85 85 +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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 +85 85 85 85 85 85 170 85 0 85 255 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +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 85 85 85 0 0 0 +0 0 0 85 85 85 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 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 170 85 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 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 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 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 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 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 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 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 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 0 0 0 +0 0 0 0 0 0 0 0 0 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 170 0 85 85 85 0 0 0 +85 85 85 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 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 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 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 85 255 85 170 85 0 170 85 0 170 85 0 85 255 85 +170 85 0 170 85 0 0 170 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 +0 0 0 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 +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 +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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 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 0 170 85 0 +255 255 85 170 85 0 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 85 255 85 170 85 0 170 85 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 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 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 +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 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 0 0 0 +0 0 0 0 0 0 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 85 0 255 255 85 +85 255 85 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 85 255 85 170 85 0 0 0 0 +85 85 85 0 0 0 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 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 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 85 255 85 +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 85 85 85 170 170 170 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 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 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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 85 0 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 170 85 0 255 255 85 170 85 0 +170 85 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 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 85 85 85 0 0 0 0 0 0 0 0 0 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +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 85 0 255 255 85 85 255 85 255 255 85 +170 170 170 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 255 255 85 +85 255 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +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 85 0 255 255 85 255 255 85 255 255 85 +255 255 255 255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 255 255 85 +170 85 0 170 85 0 0 170 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 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 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 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 85 0 85 255 85 255 255 85 170 170 170 255 255 255 +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 255 255 85 85 255 85 255 255 85 +255 255 85 85 255 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 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 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 0 0 0 0 0 0 0 0 0 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 255 255 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 85 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 170 85 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 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 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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 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 85 0 170 85 0 255 255 85 255 255 85 255 255 255 170 170 170 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +170 85 0 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +255 255 85 85 255 85 170 85 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 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 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 85 85 255 85 255 255 85 170 170 170 255 255 255 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 85 255 85 170 85 0 +255 255 85 170 85 0 170 85 0 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 170 170 170 +85 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 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 255 255 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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 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 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 255 255 85 85 255 85 255 255 85 170 85 0 170 85 0 +170 85 0 85 255 85 255 255 85 85 85 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 85 255 85 170 170 170 170 170 170 +85 85 85 170 170 170 170 170 170 170 85 0 170 170 170 170 170 170 +85 255 85 170 170 170 170 85 0 170 170 170 85 255 85 255 85 85 +85 255 85 170 170 170 255 255 85 85 85 85 255 255 85 170 170 170 +85 255 85 170 170 170 255 255 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 255 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 170 85 0 0 170 0 85 85 85 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 85 255 85 +255 85 85 85 255 85 85 85 85 255 85 85 85 85 85 170 170 170 +170 85 0 170 170 170 85 85 85 85 255 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 +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 255 255 85 170 85 0 255 255 85 85 85 85 85 85 85 +255 255 85 170 170 170 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 170 170 170 170 85 0 170 170 170 +170 170 170 255 255 85 170 170 170 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 +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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 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 255 255 85 +255 255 85 255 255 85 255 255 85 170 85 0 170 85 0 0 170 0 +0 0 0 170 85 0 170 85 0 0 170 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 170 170 170 85 85 85 +170 170 170 85 85 85 85 85 85 170 170 170 170 85 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 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 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +170 85 0 255 255 85 85 255 85 255 255 85 255 255 85 170 85 0 +170 85 0 255 255 85 170 85 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 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 +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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 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 255 255 85 255 255 85 +85 255 85 170 85 0 0 170 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 +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 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 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 0 170 85 0 255 255 85 +85 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 255 255 85 85 255 85 255 255 85 255 255 85 170 85 0 +85 255 85 170 85 0 170 85 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 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 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 170 85 0 255 255 85 85 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 85 255 85 +170 85 0 170 85 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 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 +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 +0 0 0 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 85 170 85 0 +255 255 85 170 85 0 255 255 85 170 85 0 255 255 85 85 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 255 255 85 85 255 85 170 85 0 170 85 0 +0 170 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 85 85 85 +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 85 85 85 0 0 0 +0 0 0 0 0 0 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 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 170 85 0 255 255 85 170 85 0 85 255 85 +255 255 85 85 255 85 170 85 0 170 85 0 85 255 85 170 85 0 +0 0 0 0 0 0 85 85 85 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 +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 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 85 85 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 255 255 85 +170 85 0 170 85 0 85 255 85 170 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 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 85 85 85 +0 0 0 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 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 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 255 255 85 +170 85 0 255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 +255 255 85 85 255 85 170 85 0 255 255 85 170 85 0 85 255 85 +170 85 0 170 85 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 +85 85 85 0 0 0 0 0 0 0 0 0 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 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 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 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 +0 0 0 0 0 0 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 85 255 85 +170 85 0 255 255 85 170 85 0 85 255 85 170 85 0 170 85 0 +0 170 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 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 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 170 170 170 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 255 85 255 255 85 +170 85 0 255 255 85 255 255 85 170 85 0 85 255 85 170 85 0 +255 255 85 170 85 0 0 170 0 170 85 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 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 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 +85 85 85 0 0 0 170 170 170 170 170 170 170 170 170 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 170 85 0 170 85 0 +0 170 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 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 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 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 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 +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 +0 0 0 0 0 0 0 0 0 0 0 0 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 170 85 0 0 170 0 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 +85 85 85 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 +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 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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 85 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +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 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 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 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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 170 170 170 170 170 170 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 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 170 170 170 255 255 255 170 170 170 85 85 85 +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 +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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 170 170 170 170 170 170 +255 255 255 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 +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 255 255 255 170 170 170 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 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 +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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 170 170 170 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 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 +85 85 85 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 85 85 85 85 85 85 +85 85 85 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 85 85 85 170 170 170 +170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 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 85 85 85 +0 0 0 0 0 0 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 170 170 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 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 +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 0 0 0 0 0 0 +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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 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 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 +85 85 85 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 0 0 0 85 85 85 +0 0 0 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 85 85 85 0 0 0 +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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 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 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 +85 85 85 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 0 0 0 0 0 0 +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 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 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 170 170 170 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 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 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 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +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 85 85 85 0 0 0 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 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 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 85 85 85 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 +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 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 85 85 85 170 170 170 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 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 +85 85 85 0 0 0 0 0 0 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 +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 85 85 85 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 85 85 85 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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 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 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 +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 +0 0 0 85 85 85 0 0 0 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 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 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 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 85 85 85 +0 0 0 0 0 0 85 85 85 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 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 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 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 255 255 255 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 +85 85 85 170 170 170 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 +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 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 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 170 170 170 170 170 170 +255 255 255 255 255 255 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 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 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 +85 85 85 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 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 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 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 +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 170 170 170 170 170 170 255 255 255 +255 255 255 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 85 85 85 +170 170 170 85 85 85 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 +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 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 85 85 85 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +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 85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 +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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 85 85 85 +0 0 0 0 0 0 85 85 85 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 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 +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 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 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 85 85 85 +170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 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 85 85 85 85 85 85 +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 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 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 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 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 170 170 170 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 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 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 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 +85 85 85 0 0 0 0 0 0 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 +85 85 85 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 0 0 0 85 85 85 +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 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 85 85 85 170 170 170 170 170 170 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 255 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 85 85 85 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 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 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 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 +85 85 85 170 170 170 170 170 170 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 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 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 85 85 85 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 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 170 170 170 255 255 255 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 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 +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 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 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 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 85 85 85 85 85 85 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 85 85 85 0 0 0 0 0 0 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 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 170 170 170 255 255 255 170 170 170 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +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 85 85 85 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 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 +85 85 85 255 255 255 170 170 170 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 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 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 +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 +85 85 85 85 85 85 255 255 255 255 255 255 255 255 255 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 +255 255 255 170 170 170 0 0 0 0 0 0 85 85 85 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 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 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 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 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 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 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 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 0 0 0 85 85 85 +85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 85 85 85 +85 85 85 0 0 0 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 +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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 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 85 85 85 +170 170 170 255 255 255 255 255 255 255 255 255 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 +0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 170 170 170 +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 85 85 85 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 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 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 85 85 85 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 +85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 255 255 255 +255 255 255 170 170 170 85 85 85 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +170 170 170 170 170 170 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 0 0 0 +0 0 0 0 0 0 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 85 85 85 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 0 0 0 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 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 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 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 255 255 255 +255 255 255 170 170 170 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 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 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 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 85 85 85 170 170 170 +255 255 255 170 170 170 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 170 170 170 +0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 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 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 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 85 85 85 0 0 0 85 85 85 0 0 0 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 255 255 255 +170 170 170 170 170 170 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 255 255 255 255 255 255 0 0 0 0 0 0 85 85 85 +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 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 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 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 255 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 255 255 255 170 170 170 170 170 170 170 170 170 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 0 0 0 85 85 85 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 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 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 170 170 170 255 255 255 170 170 170 170 170 170 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 170 170 170 +170 170 170 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 85 85 85 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 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 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 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 +255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 170 170 170 255 255 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +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 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 +85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +85 85 85 170 170 170 170 170 170 170 170 170 170 85 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 170 85 0 +170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +170 85 0 170 170 170 85 85 85 0 0 0 85 85 85 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 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +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 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 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 170 85 0 170 170 170 170 170 170 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 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 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 85 85 85 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 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 170 85 0 85 255 85 170 85 0 170 170 170 85 85 85 +85 85 85 0 0 0 0 0 0 85 85 85 170 85 0 85 255 85 +170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 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 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 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 0 0 0 0 0 0 0 0 0 0 0 0 +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 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 170 85 0 170 170 170 170 85 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 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 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 255 85 85 170 170 170 85 255 85 170 85 0 +85 85 85 85 85 85 170 85 0 85 85 85 170 170 170 85 85 85 +170 170 170 170 85 0 85 85 85 85 85 85 85 85 85 85 85 85 +170 85 0 85 255 85 85 85 85 85 85 85 85 85 85 170 85 0 +85 85 85 0 0 0 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 +85 85 85 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 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 +85 85 85 85 85 85 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 +85 85 85 170 85 0 170 170 170 170 85 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 255 85 170 170 170 170 170 170 170 85 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 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 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 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 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 255 85 255 85 85 170 170 170 170 170 170 +170 170 170 85 255 85 170 170 170 170 85 0 170 170 170 170 85 0 +170 170 170 85 85 85 85 255 85 170 85 0 170 170 170 170 85 0 +170 170 170 170 170 170 170 85 0 85 85 85 85 85 85 85 255 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 85 85 85 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 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 170 170 170 170 170 170 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 255 255 85 85 85 85 85 85 85 85 85 85 +85 255 85 255 85 85 170 170 170 170 85 0 170 170 170 85 255 85 +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 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 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 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 170 85 0 170 170 170 170 170 170 255 255 85 +170 170 170 255 85 85 170 170 170 170 170 170 255 255 85 170 170 170 +85 255 85 170 170 170 255 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 170 85 0 +85 85 85 0 0 0 0 0 0 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 +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 85 85 85 170 170 170 85 85 85 0 0 0 85 85 85 +85 85 85 170 85 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 85 85 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 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 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 170 85 0 +170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 85 255 85 170 85 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 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 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 170 170 170 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 170 170 170 85 85 85 170 170 170 170 85 0 +170 170 170 85 255 85 170 170 170 170 85 0 170 170 170 170 170 170 +255 255 85 170 170 170 170 170 170 255 255 255 255 255 85 170 170 170 +255 255 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 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 85 85 85 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 +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 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 255 255 255 +170 170 170 255 255 255 255 255 85 170 170 170 255 255 85 170 170 170 +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 255 85 85 170 170 170 170 170 170 +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 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 85 85 85 85 85 85 170 85 0 85 85 85 +85 85 85 255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 +255 255 85 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 +170 170 170 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 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 +85 85 85 170 170 170 170 170 170 85 85 85 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 85 255 85 170 170 170 255 255 85 255 255 255 255 255 255 +255 255 255 170 170 170 255 255 255 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 255 255 85 255 255 255 +255 255 85 255 255 255 255 255 85 170 170 170 170 170 170 170 85 0 +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 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 85 85 85 85 85 85 +85 85 85 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 +255 255 255 255 255 255 255 255 85 255 255 255 255 255 255 170 170 170 +255 255 85 85 85 85 85 85 85 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 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 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 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 170 170 170 170 170 170 170 170 170 255 255 255 170 170 170 +255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 255 170 170 170 255 255 85 170 170 170 255 255 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 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 85 85 85 170 85 0 170 170 170 +255 255 85 170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 +170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 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 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 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 0 0 0 +85 85 85 170 85 0 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 85 255 255 255 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 255 85 255 255 255 255 255 255 +170 170 170 255 255 255 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 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 85 255 85 170 170 170 +170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 85 170 170 170 170 170 170 255 255 255 +170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 255 255 85 +170 170 170 170 85 0 85 85 85 0 0 0 0 0 0 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 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 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 255 255 85 170 170 170 255 255 255 +255 255 255 170 170 170 255 255 255 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 255 255 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 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 170 85 0 170 170 170 +170 170 170 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 85 170 170 170 +255 255 85 255 255 255 170 170 170 255 255 255 170 170 170 170 170 170 +170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 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 +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 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 85 85 85 170 170 170 170 170 170 255 255 255 170 170 170 +255 255 255 170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 +255 85 85 170 170 170 170 170 170 170 170 170 255 255 255 255 255 255 +170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 +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 85 85 85 85 85 85 170 170 170 +255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 85 255 255 255 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 255 85 +170 170 170 170 85 0 85 85 85 0 0 0 85 85 85 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 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 85 85 85 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 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 85 170 170 170 170 170 170 +255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 255 85 85 +85 255 85 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 85 170 170 170 170 170 170 +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 85 85 85 255 255 85 +170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 +255 255 255 170 170 170 170 170 170 170 170 170 170 170 170 255 85 85 +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 85 85 85 0 0 0 +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 +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 170 170 170 170 170 170 170 170 170 +85 85 85 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 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 85 255 85 +255 85 85 170 170 170 255 255 85 170 170 170 170 170 170 255 255 255 +255 255 255 170 170 170 255 255 255 255 255 255 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +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 85 170 170 170 255 255 85 255 255 255 255 255 255 +170 170 170 170 170 170 255 255 85 170 170 170 255 85 85 85 255 85 +170 170 170 170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 +170 85 0 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 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 85 85 85 85 85 85 85 85 85 170 170 170 255 255 85 +170 170 170 170 85 0 170 170 170 170 170 170 170 85 0 85 85 85 +170 170 170 170 85 0 85 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 85 170 170 170 170 170 170 +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 85 85 85 170 85 0 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 170 170 170 170 170 170 170 85 0 170 170 170 85 85 85 +170 170 170 170 170 170 170 85 0 170 170 170 170 85 0 85 85 85 +85 255 85 85 85 85 0 0 0 0 0 0 0 0 0 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 +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 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 170 85 0 85 85 85 170 170 170 +170 85 0 170 170 170 85 255 85 170 85 0 170 170 170 85 85 85 +170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 255 255 255 +255 255 85 255 255 255 170 170 170 170 170 170 170 170 170 170 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 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 85 255 85 170 170 170 +170 85 0 170 85 0 170 170 170 85 255 85 85 85 85 170 170 170 +170 85 0 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 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 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 85 85 85 170 85 0 85 85 85 +170 170 170 170 85 0 170 170 170 85 85 85 170 170 170 170 85 0 +170 170 170 85 255 85 170 85 0 170 170 170 170 170 170 170 170 170 +255 255 255 170 170 170 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 85 0 170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 170 85 0 +170 170 170 85 255 85 170 85 0 170 170 170 170 85 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 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 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 85 85 85 +85 255 85 170 170 170 170 85 0 170 170 170 170 85 0 85 255 85 +170 170 170 170 85 0 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 255 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 85 85 85 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 170 85 0 +170 170 170 85 85 85 170 170 170 170 85 0 170 170 170 85 85 85 +170 85 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 85 85 85 0 0 0 85 85 85 170 85 0 +85 85 85 255 85 85 85 255 85 170 85 0 170 170 170 170 170 170 +170 85 0 170 170 170 85 85 85 255 255 85 170 170 170 170 170 170 +255 255 255 170 170 170 255 255 255 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 85 0 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 255 85 85 85 85 170 170 170 +85 255 85 255 85 85 170 170 170 85 255 85 255 85 85 85 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +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 85 85 85 +85 85 85 85 255 85 255 85 85 170 170 170 85 255 85 170 85 0 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 255 255 +170 170 170 255 255 255 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +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 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 +85 85 85 255 255 85 170 170 170 170 85 0 170 170 170 85 85 85 +170 85 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 85 85 85 +170 170 170 170 85 0 170 170 170 170 85 0 170 170 170 170 170 170 +170 85 0 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 255 255 255 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +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 85 85 85 170 170 170 +170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 170 85 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 85 85 85 85 85 85 +170 85 0 85 255 85 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 170 170 170 170 170 170 170 170 170 255 255 255 255 255 255 +255 255 255 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 170 170 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 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 85 85 85 +85 85 85 170 85 0 170 170 170 170 85 0 170 170 170 170 170 170 +170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 255 255 255 +170 170 170 255 255 255 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 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 170 170 170 85 0 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 +255 255 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 85 85 85 85 85 85 +85 85 85 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 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 0 85 85 85 +170 85 0 85 255 85 170 170 170 170 170 170 170 170 170 255 255 85 +255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 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 170 170 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 255 85 +170 170 170 255 255 85 170 170 170 255 255 85 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 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 85 85 85 85 85 85 170 85 0 170 170 170 170 170 170 +255 255 85 170 170 170 255 255 255 255 255 85 255 255 255 255 255 255 +170 170 170 255 255 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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 +170 170 170 170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 +170 170 170 255 255 255 170 170 170 255 255 255 255 255 85 255 255 255 +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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 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 85 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 +255 255 85 170 170 170 170 170 170 170 85 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 170 170 170 +255 255 85 170 170 170 255 255 85 170 170 170 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 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 170 170 +255 255 85 170 170 170 255 255 85 255 255 255 170 170 170 255 255 255 +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 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 85 0 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 255 255 255 170 170 170 255 255 255 255 255 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 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +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 85 85 85 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 170 170 170 170 85 0 85 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 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 +170 170 170 170 170 170 255 255 85 170 170 170 255 255 255 255 255 255 +255 255 85 255 255 255 170 170 170 255 255 255 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 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 85 85 85 85 85 85 +255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 255 170 170 170 255 255 85 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 85 85 85 85 85 85 +85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 170 170 170 +170 85 0 170 170 170 170 85 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 85 85 85 85 85 85 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 +170 170 170 255 255 255 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 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 85 85 85 170 85 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 170 85 0 +85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 170 170 170 170 85 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 0 0 0 0 0 0 0 0 0 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 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 +85 85 85 85 255 85 170 85 0 170 170 170 170 85 0 170 170 170 +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 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 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 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 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.2.3 From bc0fd67feba2e0770aad85393500ba77c6489f1c Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Mon, 16 Mar 2009 16:56:01 +0000 Subject: dm ioctl: validate name length when renaming When renaming a mapped device validate the length of the new name. The rename ioctl accepted any correctly-terminated string enclosed within the data passed from userspace. The other ioctls enforce a size limit of DM_NAME_LEN. If the name is changed and becomes longer than that, the device can no longer be addressed by name. Fix it by properly checking for device name length (including terminating zero). Cc: stable@kernel.org Signed-off-by: Milan Broz Reviewed-by: Jonathan Brassow Reviewed-by: Alasdair G Kergon Signed-off-by: Alasdair G Kergon --- drivers/md/dm-ioctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 54d0588fc1f6..977f36612e83 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -704,7 +704,8 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size) char *new_name = (char *) param + param->data_start; if (new_name < param->data || - invalid_str(new_name, (void *) param + param_size)) { + invalid_str(new_name, (void *) param + param_size) || + strlen(new_name) > DM_NAME_LEN - 1) { DMWARN("Invalid new logical volume name supplied."); return -EINVAL; } -- cgit v1.2.3 From f80a557008462a0a4adef25407f1872e793d8dd5 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 16 Mar 2009 17:44:26 +0000 Subject: dm table: rework reference counting fix Fix an error introduced in dm-table-rework-reference-counting.patch. When there is failure after table initialization, we need to use dm_table_destroy, not dm_table_put, to free the table. dm_table_put may be used only after dm_table_get. Cc: Kiyoshi Ueda Signed-off-by: Mikulas Patocka Reviewed-by: Jonathan Brassow Reviewed-by: Alasdair G Kergon Signed-off-by: Alasdair G Kergon --- drivers/md/dm-ioctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 977f36612e83..f01096549a93 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1064,7 +1064,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size) r = populate_table(t, param, param_size); if (r) { - dm_table_put(t); + dm_table_destroy(t); goto out; } @@ -1072,7 +1072,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size) hc = dm_get_mdptr(md); if (!hc || hc->md != md) { DMWARN("device has been removed from the dev hash table."); - dm_table_put(t); + dm_table_destroy(t); up_write(&_hash_lock); r = -ENXIO; goto out; -- cgit v1.2.3 From d659e6cc98766a1a61d6bdd283f95d149abd7719 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 16 Mar 2009 17:44:30 +0000 Subject: dm io: respect BIO_MAX_PAGES limit dm-io calls bio_get_nr_vecs to get the maximum number of pages to use for a given device. It allocates one additional bio_vec to use internally but failed to respect BIO_MAX_PAGES, so fix this. This was the likely cause of: https://bugzilla.redhat.com/show_bug.cgi?id=173153 Cc: stable@kernel.org Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm-io.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index f14813be4eff..36e2b5e46a6b 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -292,6 +292,8 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, (PAGE_SIZE >> SECTOR_SHIFT)); num_bvecs = 1 + min_t(int, bio_get_nr_vecs(where->bdev), num_bvecs); + if (unlikely(num_bvecs > BIO_MAX_PAGES)) + num_bvecs = BIO_MAX_PAGES; bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios); bio->bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; -- cgit v1.2.3 From b2174eebd1fadb76454dad09a1dacbc17081e6b0 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Mon, 16 Mar 2009 17:44:33 +0000 Subject: dm crypt: fix kcryptd_async_done parameter In the async encryption-complete function (kcryptd_async_done), the crypto_async_request passed in may be different from the one passed to crypto_ablkcipher_encrypt/decrypt. Only crypto_async_request->data is guaranteed to be same as the one passed in. The current kcryptd_async_done uses the passed-in crypto_async_request directly which may cause the AES-NI-based AES algorithm implementation to panic. This patch fixes this bug by only using crypto_async_request->data, which points to dm_crypt_request, the crypto_async_request passed in. The original data (convert_context) is gotten from dm_crypt_request. [mbroz@redhat.com: reworked] Cc: stable@kernel.org Signed-off-by: Huang Ying Cc: Herbert Xu Signed-off-by: Milan Broz Signed-off-by: Andrew Morton Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 35bda49796fb..ebab49f8cc1d 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -60,6 +60,7 @@ struct dm_crypt_io { }; struct dm_crypt_request { + struct convert_context *ctx; struct scatterlist sg_in; struct scatterlist sg_out; }; @@ -335,6 +336,18 @@ static void crypt_convert_init(struct crypt_config *cc, init_completion(&ctx->restart); } +static struct dm_crypt_request *dmreq_of_req(struct crypt_config *cc, + struct ablkcipher_request *req) +{ + return (struct dm_crypt_request *)((char *)req + cc->dmreq_start); +} + +static struct ablkcipher_request *req_of_dmreq(struct crypt_config *cc, + struct dm_crypt_request *dmreq) +{ + return (struct ablkcipher_request *)((char *)dmreq - cc->dmreq_start); +} + static int crypt_convert_block(struct crypt_config *cc, struct convert_context *ctx, struct ablkcipher_request *req) @@ -345,10 +358,11 @@ static int crypt_convert_block(struct crypt_config *cc, u8 *iv; int r = 0; - dmreq = (struct dm_crypt_request *)((char *)req + cc->dmreq_start); + dmreq = dmreq_of_req(cc, req); iv = (u8 *)ALIGN((unsigned long)(dmreq + 1), crypto_ablkcipher_alignmask(cc->tfm) + 1); + dmreq->ctx = ctx; sg_init_table(&dmreq->sg_in, 1); sg_set_page(&dmreq->sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, bv_in->bv_offset + ctx->offset_in); @@ -395,8 +409,9 @@ static void crypt_alloc_req(struct crypt_config *cc, cc->req = mempool_alloc(cc->req_pool, GFP_NOIO); ablkcipher_request_set_tfm(cc->req, cc->tfm); ablkcipher_request_set_callback(cc->req, CRYPTO_TFM_REQ_MAY_BACKLOG | - CRYPTO_TFM_REQ_MAY_SLEEP, - kcryptd_async_done, ctx); + CRYPTO_TFM_REQ_MAY_SLEEP, + kcryptd_async_done, + dmreq_of_req(cc, cc->req)); } /* @@ -821,7 +836,8 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io) static void kcryptd_async_done(struct crypto_async_request *async_req, int error) { - struct convert_context *ctx = async_req->data; + struct dm_crypt_request *dmreq = async_req->data; + struct convert_context *ctx = dmreq->ctx; struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx); struct crypt_config *cc = io->target->private; @@ -830,7 +846,7 @@ static void kcryptd_async_done(struct crypto_async_request *async_req, return; } - mempool_free(ablkcipher_request_cast(async_req), cc->req_pool); + mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool); if (!atomic_dec_and_test(&ctx->pending)) return; -- cgit v1.2.3 From b35f8caa0890169000fec22902290d9a15274cbd Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Mon, 16 Mar 2009 17:44:36 +0000 Subject: dm crypt: wait for endio to complete before destruction The following oops has been reported when dm-crypt runs over a loop device. ... [ 70.381058] Process loop0 (pid: 4268, ti=cf3b2000 task=cf1cc1f0 task.ti=cf3b2000) ... [ 70.381058] Call Trace: [ 70.381058] [] ? crypt_dec_pending+0x5e/0x62 [dm_crypt] [ 70.381058] [] ? crypt_endio+0xa2/0xaa [dm_crypt] [ 70.381058] [] ? crypt_endio+0x0/0xaa [dm_crypt] [ 70.381058] [] ? bio_endio+0x2b/0x2e [ 70.381058] [] ? dec_pending+0x224/0x23b [dm_mod] [ 70.381058] [] ? clone_endio+0x79/0xa4 [dm_mod] [ 70.381058] [] ? clone_endio+0x0/0xa4 [dm_mod] [ 70.381058] [] ? bio_endio+0x2b/0x2e [ 70.381058] [] ? loop_thread+0x380/0x3b7 [ 70.381058] [] ? do_lo_send_aops+0x0/0x165 [ 70.381058] [] ? autoremove_wake_function+0x0/0x33 [ 70.381058] [] ? loop_thread+0x0/0x3b7 When a table is being replaced, it waits for I/O to complete before destroying the mempool, but the endio function doesn't call mempool_free() until after completing the bio. Fix it by swapping the order of those two operations. The same problem occurs in dm.c with md referenced after dec_pending. Again, we swap the order. Cc: stable@kernel.org Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 17 ++++++++++------- drivers/md/dm.c | 32 +++++++++++++++++++------------- 2 files changed, 29 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index ebab49f8cc1d..bfefd079a955 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -568,19 +568,22 @@ static void crypt_inc_pending(struct dm_crypt_io *io) static void crypt_dec_pending(struct dm_crypt_io *io) { struct crypt_config *cc = io->target->private; + struct bio *base_bio = io->base_bio; + struct dm_crypt_io *base_io = io->base_io; + int error = io->error; if (!atomic_dec_and_test(&io->pending)) return; - if (likely(!io->base_io)) - bio_endio(io->base_bio, io->error); + mempool_free(io, cc->io_pool); + + if (likely(!base_io)) + bio_endio(base_bio, error); else { - if (io->error && !io->base_io->error) - io->base_io->error = io->error; - crypt_dec_pending(io->base_io); + if (error && !base_io->error) + base_io->error = error; + crypt_dec_pending(base_io); } - - mempool_free(io, cc->io_pool); } /* diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 51ba1db4b3e7..8d40f27cce89 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -525,9 +525,12 @@ static int __noflush_suspending(struct mapped_device *md) static void dec_pending(struct dm_io *io, int error) { unsigned long flags; + int io_error; + struct bio *bio; + struct mapped_device *md = io->md; /* Push-back supersedes any I/O errors */ - if (error && !(io->error > 0 && __noflush_suspending(io->md))) + if (error && !(io->error > 0 && __noflush_suspending(md))) io->error = error; if (atomic_dec_and_test(&io->io_count)) { @@ -537,24 +540,27 @@ static void dec_pending(struct dm_io *io, int error) * This must be handled before the sleeper on * suspend queue merges the pushback list. */ - spin_lock_irqsave(&io->md->pushback_lock, flags); - if (__noflush_suspending(io->md)) - bio_list_add(&io->md->pushback, io->bio); + spin_lock_irqsave(&md->pushback_lock, flags); + if (__noflush_suspending(md)) + bio_list_add(&md->pushback, io->bio); else /* noflush suspend was interrupted. */ io->error = -EIO; - spin_unlock_irqrestore(&io->md->pushback_lock, flags); + spin_unlock_irqrestore(&md->pushback_lock, flags); } end_io_acct(io); - if (io->error != DM_ENDIO_REQUEUE) { - trace_block_bio_complete(io->md->queue, io->bio); + io_error = io->error; + bio = io->bio; - bio_endio(io->bio, io->error); - } + free_io(md, io); + + if (io_error != DM_ENDIO_REQUEUE) { + trace_block_bio_complete(md->queue, bio); - free_io(io->md, io); + bio_endio(bio, io_error); + } } } @@ -562,6 +568,7 @@ static void clone_endio(struct bio *bio, int error) { int r = 0; struct dm_target_io *tio = bio->bi_private; + struct dm_io *io = tio->io; struct mapped_device *md = tio->io->md; dm_endio_fn endio = tio->ti->type->end_io; @@ -585,15 +592,14 @@ static void clone_endio(struct bio *bio, int error) } } - dec_pending(tio->io, error); - /* * Store md for cleanup instead of tio which is about to get freed. */ bio->bi_private = md->bs; - bio_put(bio); free_tio(md, tio); + bio_put(bio); + dec_pending(io, error); } static sector_t max_io_len(struct mapped_device *md, -- cgit v1.2.3 From 6158425be398936af1fd04451f78ffad01529cb0 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 12 Mar 2009 18:18:49 -0400 Subject: ath9k: implement IO serialization All 802.11n PCI devices (Cardbus, PCI, mini-PCI) require serialization of IO when on non-uniprocessor systems. PCI express devices not not require this. This should fix our only last standing open ath9k kernel.org bugzilla bug report: http://bugzilla.kernel.org/show_bug.cgi?id=12110 A port is probably required to older kernels and I can work on that. Cc: stable@kernel.org Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/ath9k.h | 4 ++-- drivers/net/wireless/ath9k/core.h | 33 +++++++++++++++++++++++++++++++++ drivers/net/wireless/ath9k/hw.c | 19 +++++++++++++++++++ drivers/net/wireless/ath9k/main.c | 1 + 4 files changed, 55 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath9k/ath9k.h b/drivers/net/wireless/ath9k/ath9k.h index d27813502953..6650f609ece4 100644 --- a/drivers/net/wireless/ath9k/ath9k.h +++ b/drivers/net/wireless/ath9k/ath9k.h @@ -587,8 +587,8 @@ struct ath9k_country_entry { u8 iso[3]; }; -#define REG_WRITE(_ah, _reg, _val) iowrite32(_val, _ah->ah_sh + _reg) -#define REG_READ(_ah, _reg) ioread32(_ah->ah_sh + _reg) +#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val)) +#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg)) #define SM(_v, _f) (((_v) << _f##_S) & _f) #define MS(_v, _f) (((_v) & _f) >> _f##_S) diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index 4ca2aed236e0..139566cbbf65 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h @@ -701,6 +701,7 @@ struct ath_softc { struct ath_hal *sc_ah; void __iomem *mem; spinlock_t sc_resetlock; + spinlock_t sc_serial_rw; struct mutex mutex; u8 sc_curbssid[ETH_ALEN]; @@ -751,4 +752,36 @@ int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); int ath_cabq_update(struct ath_softc *); +/* + * Read and write, they both share the same lock. We do this to serialize + * reads and writes on Atheros 802.11n PCI devices only. This is required + * as the FIFO on these devices can only accept sanely 2 requests. After + * that the device goes bananas. Serializing the reads/writes prevents this + * from happening. + */ + +static inline void ath9k_iowrite32(struct ath_hal *ah, u32 reg_offset, u32 val) +{ + if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) { + unsigned long flags; + spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); + iowrite32(val, ah->ah_sc->mem + reg_offset); + spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); + } else + iowrite32(val, ah->ah_sc->mem + reg_offset); +} + +static inline unsigned int ath9k_ioread32(struct ath_hal *ah, u32 reg_offset) +{ + u32 val; + if (ah->ah_config.serialize_regmode == SER_REG_MODE_ON) { + unsigned long flags; + spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); + val = ioread32(ah->ah_sc->mem + reg_offset); + spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); + } else + val = ioread32(ah->ah_sc->mem + reg_offset); + return val; +} + #endif /* CORE_H */ diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 34474edefc97..5c870436fc5f 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -437,6 +437,25 @@ static void ath9k_hw_set_defaults(struct ath_hal *ah) } ah->ah_config.intr_mitigation = 1; + + /* + * We need this for PCI devices only (Cardbus, PCI, miniPCI) + * _and_ if on non-uniprocessor systems (Multiprocessor/HT). + * This means we use it for all AR5416 devices, and the few + * minor PCI AR9280 devices out there. + * + * Serialization is required because these devices do not handle + * well the case of two concurrent reads/writes due to the latency + * involved. During one read/write another read/write can be issued + * on another CPU while the previous read/write may still be working + * on our hardware, if we hit this case the hardware poops in a loop. + * We prevent this by serializing reads and writes. + * + * This issue is not present on PCI-Express devices or pre-AR5416 + * devices (legacy, 802.11abg). + */ + if (num_possible_cpus() > 1) + ah->ah_config.serialize_regmode = SER_REG_MODE_AUTO; } static struct ath_hal_5416 *ath9k_hw_newstate(u16 devid, diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 0e80990d8e84..3c04044a60bd 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c @@ -1336,6 +1336,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) printk(KERN_ERR "Unable to create debugfs files\n"); spin_lock_init(&sc->sc_resetlock); + spin_lock_init(&sc->sc_serial_rw); mutex_init(&sc->mutex); tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, -- cgit v1.2.3 From 5ec905a8df3fa877566ba98298433fbfb3d688cc Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 12 Mar 2009 18:18:50 -0400 Subject: ath9k: AR9280 PCI devices must serialize IO as well Cc: stable@kernel.org Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index 5c870436fc5f..c38a00bbce64 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -687,7 +687,8 @@ static struct ath_hal *ath9k_hw_do_attach(u16 devid, struct ath_softc *sc, } if (ah->ah_config.serialize_regmode == SER_REG_MODE_AUTO) { - if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI) { + if (ah->ah_macVersion == AR_SREV_VERSION_5416_PCI || + (AR_SREV_9280(ah) && !ah->ah_isPciExpress)) { ah->ah_config.serialize_regmode = SER_REG_MODE_ON; } else { -- cgit v1.2.3 From 640c65eae673d2caf6e7bf61c1eb4e9513b88fda Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Mon, 16 Mar 2009 21:47:33 +0200 Subject: zd1211rw: Do not panic on device eject when associated zd_op_tx() must not return an arbitrary error value since that can leave mac80211 trying to retransmit the frame and with the extra data pushed into the beginning of the skb on every attempt, this will end up causing a kernel panic (skb_under_panic from skb_push call). This can happen, e.g., when ejecting the device when associated. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/zd1211rw/zd_mac.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index a611ad857983..847057d682b1 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -575,13 +575,17 @@ static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) r = fill_ctrlset(mac, skb); if (r) - return r; + goto fail; info->rate_driver_data[0] = hw; r = zd_usb_tx(&mac->chip.usb, skb); if (r) - return r; + goto fail; + return 0; + +fail: + dev_kfree_skb(skb); return 0; } -- cgit v1.2.3 From 5b10916ea0a62920204517e1c4ce14560b4f96ab Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 10 Mar 2009 20:42:55 -0700 Subject: USB: usbtmc: fix stupid bug in open() open() will never succeed, as we always return -ENODEV. Fix this obvious bug. Thanks to Jouni Ryno for reporting it. Reported-by: Jouni Ryno Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 0f5c05f6f9df..895a09839001 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -106,12 +106,13 @@ static int usbtmc_open(struct inode *inode, struct file *filp) { struct usb_interface *intf; struct usbtmc_device_data *data; - int retval = -ENODEV; + int retval = 0; intf = usb_find_interface(&usbtmc_driver, iminor(inode)); if (!intf) { printk(KERN_ERR KBUILD_MODNAME ": can not find device for minor %d", iminor(inode)); + retval = -ENODEV; goto exit; } -- cgit v1.2.3 From 228dd05dbfdd0fced8ab1a28ed73b500ba6bb0a6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Mar 2009 13:51:42 -0700 Subject: USB: usbtmc: add protocol 1 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver already supports the 1 protocol support, so just add it to the MODULE_DEVICE_TABLE entry so it properly picks up these devices. Thanks to Jouni Rynö for pointing this out. Reported-by: Jouni Ryno Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 895a09839001..c40a9b284cc9 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -50,6 +50,7 @@ static struct usb_device_id usbtmc_devices[] = { { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), }, + { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 1), }, { 0, } /* terminating entry */ }; MODULE_DEVICE_TABLE(usb, usbtmc_devices); -- cgit v1.2.3 From 6ff10464096540e14d7575a72c50d0316d003714 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 9 Mar 2009 13:44:02 -0400 Subject: USB: usbfs: keep async URBs until the device file is closed The usbfs driver manages a list of completed asynchronous URBs. But it is too eager to free the entries on this list: destroy_async() gets called whenever an interface is unbound or a device is removed, and it deallocates the outstanding struct async entries for all URBs on that interface or device. This is wrong; the user program should be able to reap an URB any time after it has completed, regardless of whether or not the interface is still bound or the device is still present. This patch (as1222) moves the code for deallocating the completed list entries from destroy_async() to usbdev_release(). The outstanding entries won't be freed until the user program has closed the device file, thereby eliminating any possibility that the remaining URBs might still be reaped. This fixes a bug in which a program can hang in the USBDEVFS_REAPURB ioctl when the device is unplugged. Reported-and-tested-by: Martin Poupe Signed-off-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 7513bb083c15..6585f527e381 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -359,11 +359,6 @@ static void destroy_async(struct dev_state *ps, struct list_head *list) spin_lock_irqsave(&ps->lock, flags); } spin_unlock_irqrestore(&ps->lock, flags); - as = async_getcompleted(ps); - while (as) { - free_async(as); - as = async_getcompleted(ps); - } } static void destroy_async_on_interface(struct dev_state *ps, @@ -643,6 +638,7 @@ static int usbdev_release(struct inode *inode, struct file *file) struct dev_state *ps = file->private_data; struct usb_device *dev = ps->dev; unsigned int ifnum; + struct async *as; usb_lock_device(dev); @@ -661,6 +657,12 @@ static int usbdev_release(struct inode *inode, struct file *file) usb_unlock_device(dev); usb_put_dev(dev); put_pid(ps->disc_pid); + + as = async_getcompleted(ps); + while (as) { + free_async(as); + as = async_getcompleted(ps); + } kfree(ps); return 0; } -- cgit v1.2.3 From 7f82b6dd7015aabca2fd55fb690248f742cd67f3 Mon Sep 17 00:00:00 2001 From: Axel Wachtler Date: Thu, 5 Mar 2009 14:09:22 -0800 Subject: USB: serial: add FTDI USB/Serial converter devices Add the following devices to the USB FTDI SIO device table: Bus 001 Device 009: ID 03eb:2109 Atmel Corp. http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4187 Bus 001 Device 008: ID 1cf1:0001 http://www.dresden-elektronik.de/shop/prod75.html Bus 001 Device 007: ID 1c1f:0004 http://www.dresden-elektronik.de/shop/prod64.html Signed-off-by: Axel Wachtler Signed-off-by: Robert Richter Signed-off-by: Andrew Morton Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 3 +++ drivers/usb/serial/ftdi_sio.h | 13 +++++++++++++ 2 files changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f92f4d773374..f77339265ee6 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -663,6 +663,9 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) }, { USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) }, { USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID) }, + { USB_DEVICE(ATMEL_VID, STK541_PID) }, + { USB_DEVICE(DE_VID, STB_PID) }, + { USB_DEVICE(DE_VID, WHT_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index e300c840f8ca..f2745edabcd9 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -892,6 +892,19 @@ */ #define DIEBOLD_BCS_SE923_PID 0xfb99 +/* + * Atmel STK541 + */ +#define ATMEL_VID 0x03eb /* Vendor ID */ +#define STK541_PID 0x2109 /* Zigbee Controller */ + +/* + * Dresden Elektronic Sensor Terminal Board + */ +#define DE_VID 0x1cf1 /* Vendor ID */ +#define STB_PID 0x0001 /* Sensor Terminal Board */ +#define WHT_PID 0x0004 /* Wireless Handheld Terminal */ + /* * BmRequestType: 1100 0000b * bRequest: FTDI_E2_READ -- cgit v1.2.3 From b0d659002168146ec6b03d1ef062d8dcf05ff510 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 6 Mar 2009 14:07:43 -0800 Subject: USB: serial: ftdi: enable UART detection on gnICE JTAG adaptors blacklist interface0 Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu Signed-off-by: Andrew Morton Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio.h | 7 +++++++ 2 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f77339265ee6..ae84c326a540 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -666,6 +666,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(ATMEL_VID, STK541_PID) }, { USB_DEVICE(DE_VID, STB_PID) }, { USB_DEVICE(DE_VID, WHT_PID) }, + { USB_DEVICE(ADI_VID, ADI_GNICE_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index f2745edabcd9..daaf63db0b50 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -905,6 +905,13 @@ #define STB_PID 0x0001 /* Sensor Terminal Board */ #define WHT_PID 0x0004 /* Wireless Handheld Terminal */ +/* + * Blackfin gnICE JTAG + * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice + */ +#define ADI_VID 0x0456 +#define ADI_GNICE_PID 0xF000 + /* * BmRequestType: 1100 0000b * bRequest: FTDI_E2_READ -- cgit v1.2.3 From c6535668798b0644e1af5934c2aec0e912280449 Mon Sep 17 00:00:00 2001 From: "Robert M. Kenney" Date: Thu, 26 Feb 2009 14:58:39 -0500 Subject: USB: serial: new cp2101 device id From: Robert M. Kenney Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 027f4b7dde86..9b4082b58c5b 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -79,6 +79,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ + { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ -- cgit v1.2.3 From c497e715f93d148d751c055401568684eea0bf6b Mon Sep 17 00:00:00 2001 From: Jan Dumon Date: Tue, 10 Mar 2009 17:29:47 +0100 Subject: USB: unusual_devs: Add support for GI 0431 SD-Card interface Enable the SD-Card interface on the GI 0431 HSUPA stick 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. T: Bus=07 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 15 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=ff Prot=ff MxPS=64 #Cfgs= 1 P: Vendor=0af0 ProdID=7501 Rev= 0.00 S: Manufacturer=Option N.V. S: Product=Globetrotter HSUPA Modem C:* #Ifs=11 Cfg#= 1 Atr=a0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso 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= 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= 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= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso 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= 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= 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= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso 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= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso 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= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=89(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= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=8b(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=0a(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#=10 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=0b(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8c(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: Jan Dumon 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(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 6f59c8e510ea..bfa8db0d8aa3 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1390,6 +1390,16 @@ UNUSUAL_DEV( 0x0af0, 0x7401, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, 0 ), +/* Reported by Jan Dumon + * 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, 0x7501, 0x0000, 0x0000, + "Option", + "GI 0431 SD-Card", + US_SC_DEVICE, US_PR_DEVICE, NULL, + 0 ), + /* Reported by Ben Efros */ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, "Seagate", -- cgit v1.2.3 From eeafa64b7a4134da24d48ed944e48541f8171152 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:36 +0100 Subject: USB: atm/cxacru, fix lock imbalance We do not hold mutex in one place in cxacru_cm, but unlock it on fail path. Fix this. Signed-off-by: Jiri Slaby Cc: Simon Arlott Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/cxacru.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 5ed4ae07bac1..6789089e2461 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -485,7 +485,7 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, usb_err(instance->usbatm, "requested transfer size too large (%d, %d)\n", wbuflen, rbuflen); ret = -ENOMEM; - goto fail; + goto err; } mutex_lock(&instance->cm_serialize); @@ -565,6 +565,7 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, dbg("cm %#x", cm); fail: mutex_unlock(&instance->cm_serialize); +err: return ret; } -- cgit v1.2.3 From 909b6c3fc20ea772dc63a03986d74148fcbb1a1d Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:37 +0100 Subject: USB: image/mdc800, fix lock imbalance There is an omitted unlock in mdc800_usb_probe's fail path. Add it. Signed-off-by: Jiri Slaby Cc: Henning Zabel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/image/mdc800.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 878c77ca086e..972f20b3406c 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -499,6 +499,7 @@ static int mdc800_usb_probe (struct usb_interface *intf, retval = usb_register_dev(intf, &mdc800_class); if (retval) { dev_err(&intf->dev, "Not able to get a minor for this device.\n"); + mutex_unlock(&mdc800->io_lock); return -ENODEV; } -- cgit v1.2.3 From 46c9844c4014be53c67622dcd3ba4302f36e9cac Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:38 +0100 Subject: USB: misc/adutux, fix lock imbalance Don't unlock adutux_mutex when not held. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 7b6922e08ed1..203526542013 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -376,7 +376,7 @@ static int adu_release(struct inode *inode, struct file *file) if (dev->open_count <= 0) { dbg(1," %s : device not opened", __func__); retval = -ENODEV; - goto exit; + goto unlock; } adu_release_internal(dev); @@ -385,9 +385,9 @@ static int adu_release(struct inode *inode, struct file *file) if (!dev->open_count) /* ... and we're the last user */ adu_delete(dev); } - -exit: +unlock: mutex_unlock(&adutux_mutex); +exit: dbg(2," %s : leave, return value %d", __func__, retval); return retval; } -- cgit v1.2.3 From a08b43aee46ed4272ad7bee2c785edcf313339b3 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:39 +0100 Subject: USB: misc/vstusb, fix lock imbalance Make sure we don't leak locked vstdev->lock in vstusb_write. Unlock properly on one fail path. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/vstusb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c index 63dff9ba73c5..f26ea8dc1577 100644 --- a/drivers/usb/misc/vstusb.c +++ b/drivers/usb/misc/vstusb.c @@ -401,6 +401,7 @@ static ssize_t vstusb_write(struct file *file, const char __user *buffer, } if (copy_from_user(buf, buffer, count)) { + mutex_unlock(&vstdev->lock); dev_err(&dev->dev, "%s: can't copy_from_user\n", __func__); retval = -EFAULT; goto exit; -- cgit v1.2.3 From 49fa09215c03116449184057f062c6aea2f1d0b4 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:40 +0100 Subject: USB: wusbcore/wa-xfer, fix lock imbalance Fix locking on one wa_urb_enqueue_b's fail path. There was omitted unlock. Signed-off-by: Jiri Slaby Cc: Inaky Perez-Gonzalez Signed-off-by: Greg Kroah-Hartman --- drivers/usb/wusbcore/wa-xfer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index 238a96aee3a1..613a5fc490d3 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -921,8 +921,10 @@ static void wa_urb_enqueue_b(struct wa_xfer *xfer) result = -ENODEV; /* FIXME: segmentation broken -- kills DWA */ mutex_lock(&wusbhc->mutex); /* get a WUSB dev */ - if (urb->dev == NULL) + if (urb->dev == NULL) { + mutex_unlock(&wusbhc->mutex); goto error_dev_gone; + } wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb->dev); if (wusb_dev == NULL) { mutex_unlock(&wusbhc->mutex); -- cgit v1.2.3 From 9ea19b82f3126da4e47d6b94563a3c2cd586f6e2 Mon Sep 17 00:00:00 2001 From: Albert Pauw Date: Sun, 1 Mar 2009 09:37:52 +0100 Subject: USB: option.c: add ZTE 622 modem device Please consider this small patch for the usb option-card driver. This patch adds the ZTE 622 usb modem device. Signed-off-by: Albert Pauw Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index b7c132bded7f..ddd0a0b7e1a3 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -288,6 +288,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po /* ZTE PRODUCTS */ #define ZTE_VENDOR_ID 0x19d2 +#define ZTE_PRODUCT_MF622 0x0001 #define ZTE_PRODUCT_MF628 0x0015 #define ZTE_PRODUCT_MF626 0x0031 #define ZTE_PRODUCT_CDMA_TECH 0xfffe @@ -510,6 +511,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, + { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, -- cgit v1.2.3 From 508db8c954d55ed30f870d2c24d741ba6269d13c Mon Sep 17 00:00:00 2001 From: Karsten Wiese Date: Thu, 26 Feb 2009 01:47:48 +0100 Subject: USB: EHCI: Fix isochronous URB leak ehci-hcd uses usb_get_urb() and usb_put_urb() in an unbalanced way causing isochronous URB's kref.counts incrementing once per usb_submit_urb() call. The culprit is *usb being set to NULL when usb_put_urb() is called after URB is given back. Due to other fixes there is no need for ehci-hcd to deal with usb_get_urb() nor usb_put_urb() anymore, so patch removes their usages in ehci-hcd. Patch also makes ehci_to_hcd(ehci)->self.bandwidth_allocated adjust, if a stream finishes. Signed-off-by: Karsten Wiese Cc: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 07bcb931021b..1d0b49e3f192 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1536,7 +1536,7 @@ itd_link_urb ( struct ehci_itd, itd_list); list_move_tail (&itd->itd_list, &stream->td_list); itd->stream = iso_stream_get (stream); - itd->urb = usb_get_urb (urb); + itd->urb = urb; itd_init (ehci, stream, itd); } @@ -1645,7 +1645,7 @@ itd_complete ( (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - if (unlikely (list_empty (&stream->td_list))) { + if (unlikely(list_is_singular(&stream->td_list))) { ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth; ehci_vdbg (ehci, @@ -1656,7 +1656,6 @@ itd_complete ( iso_stream_put (ehci, stream); done: - usb_put_urb(urb); itd->urb = NULL; if (ehci->clock_frame != itd->frame || itd->index[7] != -1) { /* OK to recycle this ITD now. */ @@ -1949,7 +1948,7 @@ sitd_link_urb ( struct ehci_sitd, sitd_list); list_move_tail (&sitd->sitd_list, &stream->td_list); sitd->stream = iso_stream_get (stream); - sitd->urb = usb_get_urb (urb); + sitd->urb = urb; sitd_patch(ehci, stream, sitd, sched, packet); sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size, @@ -2034,7 +2033,7 @@ sitd_complete ( (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - if (list_empty (&stream->td_list)) { + if (list_is_singular(&stream->td_list)) { ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth; ehci_vdbg (ehci, @@ -2045,7 +2044,6 @@ sitd_complete ( iso_stream_put (ehci, stream); /* OK to recycle this SITD now that its completion callback ran. */ done: - usb_put_urb(urb); sitd->urb = NULL; sitd->stream = NULL; list_move(&sitd->sitd_list, &stream->free_list); -- cgit v1.2.3 From 391016f6e2fe3b9979b4c6880a76e5e434d6947c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 16 Mar 2009 14:21:56 -0400 Subject: USB: EHCI: expedite unlinks when the root hub is suspended This patch (as1225) fixes a bug in ehci-hcd. The condition for whether unlinked QHs can become IDLE should not be that the controller is halted, but rather that the controller isn't running. In other words when the root hub is suspended, the hardware doesn't own any QHs. This fixes a problem that can show up during hibernation: If a QH is only partially unlinked when the root hub is frozen, then when the root hub is thawed the QH won't be in the IDLE state. As a result it can't be used properly for new URB submissions. Signed-off-by: Alan Stern Reported-by: Brandon Philips Tested-by: Brandon Philips Acked-by: David Brownell Cc: Stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 3712b925b315..ecc9b66c03cd 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1095,7 +1095,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) prev->qh_next = qh->qh_next; wmb (); - if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) { + /* If the controller isn't running, we don't have to wait for it */ + if (unlikely(!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))) { /* if (unlikely (qh->reclaim != 0)) * this will recurse, probably not much */ -- cgit v1.2.3 From 0cc6bfe901b946df125d8e37186d8e45f876457d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 Mar 2009 06:53:00 -0400 Subject: USB: Option: let cdc-acm handle Sony Ericsson F3507g / Dell 5530 The generic cdc-acm driver is now the best one to handle Sony Ericsson F3507g-based devices (which the Dell 5530 is a rebrand of), now that all the pieces are in place (ie, cac477e8f1038c41b6f29d3161ce351462ef3df7). Removing the IDs from option allows cdc-acm to handle the device. Signed-off-by: Dan Williams Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ddd0a0b7e1a3..3cf765b0bedf 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -293,11 +293,6 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po #define ZTE_PRODUCT_MF626 0x0031 #define ZTE_PRODUCT_CDMA_TECH 0xfffe -/* Ericsson products */ -#define ERICSSON_VENDOR_ID 0x0bdb -#define ERICSSON_PRODUCT_F3507G_1 0x1900 -#define ERICSSON_PRODUCT_F3507G_2 0x1902 - #define BENQ_VENDOR_ID 0x04a5 #define BENQ_PRODUCT_H10 0x4068 @@ -443,7 +438,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_CINGULAR) }, /* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_GENERIC_L) }, /* Dell Wireless HSDPA 5520 */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_GENERIC_I) }, /* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */ - { USB_DEVICE(DELL_VENDOR_ID, 0x8147) }, /* Dell Wireless 5530 Mobile Broadband (3G HSPA) Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ @@ -515,8 +509,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, - { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_1) }, - { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_2) }, { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */ { } /* Terminating entry */ -- cgit v1.2.3 From 716a9c8561d9c50ec454f4fbd39a265892feda2c Mon Sep 17 00:00:00 2001 From: Moritz Muehlenhoff Date: Sat, 14 Mar 2009 00:43:21 +0100 Subject: USB: Updated unusual-devs entry for USB mass storage on Nokia 6233 Current firmware revision 5.60 still behaves the same, so update the quirk up a (non-existing) 99.99 revision. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=493415 Signed-off-by: Moritz Muehlenhoff Tested-by: Jan Heitkoetter Cc: stable Signed-off-by: Phil Dibowitz --- drivers/usb/storage/unusual_devs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index bfa8db0d8aa3..84ca4332e6b2 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -226,7 +226,7 @@ UNUSUAL_DEV( 0x0421, 0x047c, 0x0370, 0x0610, US_FL_MAX_SECTORS_64 ), /* Reported by Manuel Osdoba */ -UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x0452, +UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x9999, "Nokia", "Nokia 6233", US_SC_DEVICE, US_PR_DEVICE, NULL, -- cgit v1.2.3 From 56a21827439a4d715b510bfaf488534e6f4ad2f8 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 14 Mar 2009 20:47:39 -0700 Subject: USB: Add Vendor/Product ID for new CDMA U727 to option driver * newer versions of the Novatel Wireless U727 CDMA 3G USB stick have a different Product ID (0x5010); adding this ID makes them work just fine with the option driver Signed-off-by: Dirk Hohndel Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 3cf765b0bedf..d31fc2bcf77d 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -197,6 +197,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po /* OVATION PRODUCTS */ #define NOVATELWIRELESS_PRODUCT_MC727 0x4100 #define NOVATELWIRELESS_PRODUCT_MC950D 0x4400 +#define NOVATELWIRELESS_PRODUCT_U727 0x5010 /* FUTURE NOVATEL PRODUCTS */ #define NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED 0X6000 @@ -411,6 +412,7 @@ 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 MC727/U727/USB727 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED) }, /* Novatel EVDO product */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */ -- cgit v1.2.3 From e7f2f0d77a7b483a26054f29ba8393831b25a8a4 Mon Sep 17 00:00:00 2001 From: Achilleas Kotsis Date: Mon, 16 Mar 2009 16:35:02 +0200 Subject: USB: Add device id for Option GTM380 to option driver Option GTM380 in Modem mode uses Product ID 0x7201. This has been tested and works on production systems for over 6 months. Signed-off-by: Achilleas Kotsis Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index d31fc2bcf77d..61ebddc48497 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -89,6 +89,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po #define OPTION_PRODUCT_ETNA_MODEM_GT 0x7041 #define OPTION_PRODUCT_ETNA_MODEM_EX 0x7061 #define OPTION_PRODUCT_ETNA_KOI_MODEM 0x7100 +#define OPTION_PRODUCT_GTM380_MODEM 0x7201 #define HUAWEI_VENDOR_ID 0x12D1 #define HUAWEI_PRODUCT_E600 0x1001 @@ -322,6 +323,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTM380_MODEM) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q101) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q111) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, -- cgit v1.2.3 From 8a0845c51b2e300f5204a323b874f7f58ea0eff7 Mon Sep 17 00:00:00 2001 From: Thomas Bartosik Date: Mon, 16 Mar 2009 16:04:38 +0100 Subject: USB: storage: Unusual USB device Prolific 2507 variation added The "c-enter" USB to Toshiba 1.8" IDE enclosure needs special treatment to work flawlessly. This patch is absolutely trivial, as the integrated USB-IDE bridge is already identified to be an "unusual" device, only the bcdDevice is different (lower) to the bcdDeviceMin already included in the kernel. It is a Prolific 2507 bridge. T: Bus=02 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 4 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=067b ProdID=2507 Rev= 0.01 S: Manufacturer=Prolific Technology Inc. S: Product=ATAPI-6 Bridge Controller S: SerialNumber=00000272 C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: Thomas Bartosik Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 84ca4332e6b2..cfde74a6faa3 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -951,7 +951,9 @@ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001, US_FL_FIX_CAPACITY ), /* Reported by Richard -=[]=- */ -UNUSUAL_DEV( 0x067b, 0x2507, 0x0100, 0x0100, +/* Change to bcdDeviceMin (0x0100 to 0x0001) reported by + * Thomas Bartosik */ +UNUSUAL_DEV( 0x067b, 0x2507, 0x0001, 0x0100, "Prolific Technology Inc.", "Mass Storage Device", US_SC_DEVICE, US_PR_DEVICE, NULL, -- cgit v1.2.3 From d0573facf21d1e5cfbc1ddac272b7592722e6c01 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Mar 2009 09:22:17 -0700 Subject: Staging: benet: remove driver now that it is merged in drivers/net/ The benet driver is now in the proper place in drivers/net/benet, so we can remove the staging version. Acked-by: Sathya Perla Cc: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/benet/Kconfig | 7 - drivers/staging/benet/MAINTAINERS | 6 - drivers/staging/benet/Makefile | 14 - drivers/staging/benet/TODO | 6 - drivers/staging/benet/asyncmesg.h | 82 -- drivers/staging/benet/be_cm.h | 134 --- drivers/staging/benet/be_common.h | 53 -- drivers/staging/benet/be_ethtool.c | 348 -------- drivers/staging/benet/be_init.c | 1382 ----------------------------- drivers/staging/benet/be_int.c | 863 ------------------ drivers/staging/benet/be_netif.c | 705 --------------- drivers/staging/benet/benet.h | 429 --------- drivers/staging/benet/bestatus.h | 103 --- drivers/staging/benet/cev.h | 243 ----- drivers/staging/benet/cq.c | 211 ----- drivers/staging/benet/descriptors.h | 71 -- drivers/staging/benet/doorbells.h | 179 ---- drivers/staging/benet/ep.h | 66 -- drivers/staging/benet/eq.c | 299 ------- drivers/staging/benet/eth.c | 1273 -------------------------- drivers/staging/benet/etx_context.h | 55 -- drivers/staging/benet/funcobj.c | 565 ------------ drivers/staging/benet/fwcmd_common.h | 222 ----- drivers/staging/benet/fwcmd_common_bmap.h | 717 --------------- drivers/staging/benet/fwcmd_eth_bmap.h | 280 ------ drivers/staging/benet/fwcmd_hdr_bmap.h | 54 -- drivers/staging/benet/fwcmd_mcc.h | 94 -- drivers/staging/benet/fwcmd_opcodes.h | 244 ----- drivers/staging/benet/fwcmd_types_bmap.h | 29 - drivers/staging/benet/host_struct.h | 182 ---- drivers/staging/benet/hwlib.h | 830 ----------------- drivers/staging/benet/mpu.c | 1364 ---------------------------- drivers/staging/benet/mpu.h | 74 -- drivers/staging/benet/mpu_context.h | 46 - drivers/staging/benet/pcicfg.h | 825 ----------------- drivers/staging/benet/post_codes.h | 111 --- drivers/staging/benet/regmap.h | 68 -- 39 files changed, 12237 deletions(-) delete mode 100644 drivers/staging/benet/Kconfig delete mode 100644 drivers/staging/benet/MAINTAINERS delete mode 100644 drivers/staging/benet/Makefile delete mode 100644 drivers/staging/benet/TODO delete mode 100644 drivers/staging/benet/asyncmesg.h delete mode 100644 drivers/staging/benet/be_cm.h delete mode 100644 drivers/staging/benet/be_common.h delete mode 100644 drivers/staging/benet/be_ethtool.c delete mode 100644 drivers/staging/benet/be_init.c delete mode 100644 drivers/staging/benet/be_int.c delete mode 100644 drivers/staging/benet/be_netif.c delete mode 100644 drivers/staging/benet/benet.h delete mode 100644 drivers/staging/benet/bestatus.h delete mode 100644 drivers/staging/benet/cev.h delete mode 100644 drivers/staging/benet/cq.c delete mode 100644 drivers/staging/benet/descriptors.h delete mode 100644 drivers/staging/benet/doorbells.h delete mode 100644 drivers/staging/benet/ep.h delete mode 100644 drivers/staging/benet/eq.c delete mode 100644 drivers/staging/benet/eth.c delete mode 100644 drivers/staging/benet/etx_context.h delete mode 100644 drivers/staging/benet/funcobj.c delete mode 100644 drivers/staging/benet/fwcmd_common.h delete mode 100644 drivers/staging/benet/fwcmd_common_bmap.h delete mode 100644 drivers/staging/benet/fwcmd_eth_bmap.h delete mode 100644 drivers/staging/benet/fwcmd_hdr_bmap.h delete mode 100644 drivers/staging/benet/fwcmd_mcc.h delete mode 100644 drivers/staging/benet/fwcmd_opcodes.h delete mode 100644 drivers/staging/benet/fwcmd_types_bmap.h delete mode 100644 drivers/staging/benet/host_struct.h delete mode 100644 drivers/staging/benet/hwlib.h delete mode 100644 drivers/staging/benet/mpu.c delete mode 100644 drivers/staging/benet/mpu.h delete mode 100644 drivers/staging/benet/mpu_context.h delete mode 100644 drivers/staging/benet/pcicfg.h delete mode 100644 drivers/staging/benet/post_codes.h delete mode 100644 drivers/staging/benet/regmap.h (limited to 'drivers') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index ce6badded47a..211af86a6c55 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -73,8 +73,6 @@ source "drivers/staging/rt2860/Kconfig" source "drivers/staging/rt2870/Kconfig" -source "drivers/staging/benet/Kconfig" - source "drivers/staging/comedi/Kconfig" source "drivers/staging/asus_oled/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 9ddcc2bb3365..47a56f5ffabc 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_AGNX) += agnx/ obj-$(CONFIG_OTUS) += otus/ obj-$(CONFIG_RT2860) += rt2860/ obj-$(CONFIG_RT2870) += rt2870/ -obj-$(CONFIG_BENET) += benet/ obj-$(CONFIG_COMEDI) += comedi/ obj-$(CONFIG_ASUS_OLED) += asus_oled/ obj-$(CONFIG_PANEL) += panel/ diff --git a/drivers/staging/benet/Kconfig b/drivers/staging/benet/Kconfig deleted file mode 100644 index f6806074f998..000000000000 --- a/drivers/staging/benet/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ -config BENET - tristate "ServerEngines 10Gb NIC - BladeEngine" - depends on PCI && INET - select INET_LRO - help - This driver implements the NIC functionality for ServerEngines - 10Gb network adapter BladeEngine (EC 3210). diff --git a/drivers/staging/benet/MAINTAINERS b/drivers/staging/benet/MAINTAINERS deleted file mode 100644 index d5ce340218b3..000000000000 --- a/drivers/staging/benet/MAINTAINERS +++ /dev/null @@ -1,6 +0,0 @@ -SERVER ENGINES 10Gbe NIC - BLADE-ENGINE -P: Subbu Seetharaman -M: subbus@serverengines.com -L: netdev@vger.kernel.org -W: http://www.serverengines.com -S: Supported diff --git a/drivers/staging/benet/Makefile b/drivers/staging/benet/Makefile deleted file mode 100644 index 460b923b99bd..000000000000 --- a/drivers/staging/benet/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# Makefile to build the network driver for ServerEngine's BladeEngine -# -obj-$(CONFIG_BENET) += benet.o - -benet-y := be_init.o \ - be_int.o \ - be_netif.o \ - be_ethtool.o \ - funcobj.o \ - cq.o \ - eq.o \ - mpu.o \ - eth.o diff --git a/drivers/staging/benet/TODO b/drivers/staging/benet/TODO deleted file mode 100644 index a51dfb59a62f..000000000000 --- a/drivers/staging/benet/TODO +++ /dev/null @@ -1,6 +0,0 @@ -TODO: - - remove wrappers around common iowrite functions - - full netdev audit of common problems/issues - -Please send all patches and questions to Subbu Seetharaman - and Greg Kroah-Hartman diff --git a/drivers/staging/benet/asyncmesg.h b/drivers/staging/benet/asyncmesg.h deleted file mode 100644 index d1e779adb848..000000000000 --- a/drivers/staging/benet/asyncmesg.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __asyncmesg_amap_h__ -#define __asyncmesg_amap_h__ -#include "fwcmd_common.h" - -/* --- ASYNC_EVENT_CODES --- */ -#define ASYNC_EVENT_CODE_LINK_STATE (1) -#define ASYNC_EVENT_CODE_ISCSI (2) - -/* --- ASYNC_LINK_STATES --- */ -#define ASYNC_EVENT_LINK_DOWN (0) /* Link Down on a port */ -#define ASYNC_EVENT_LINK_UP (1) /* Link Up on a port */ - -/* - * The last 4 bytes of the async events have this common format. It allows - * the driver to distinguish [link]MCC_CQ_ENTRY[/link] structs from - * asynchronous events. Both arrive on the same completion queue. This - * structure also contains the common fields used to decode the async event. - */ -struct BE_ASYNC_EVENT_TRAILER_AMAP { - u8 rsvd0[8]; /* DWORD 0 */ - u8 event_code[8]; /* DWORD 0 */ - u8 event_type[8]; /* DWORD 0 */ - u8 rsvd1[6]; /* DWORD 0 */ - u8 async_event; /* DWORD 0 */ - u8 valid; /* DWORD 0 */ -} __packed; -struct ASYNC_EVENT_TRAILER_AMAP { - u32 dw[1]; -}; - -/* - * Applicable in Initiator, Target and NIC modes. - * A link state async event is seen by all device drivers as soon they - * create an MCC ring. Thereafter, anytime the link status changes the - * drivers will receive a link state async event. Notifications continue to - * be sent until a driver destroys its MCC ring. A link down event is - * reported when either port loses link. A link up event is reported - * when either port regains link. When BE's failover mechanism is enabled, a - * link down on the active port causes traffic to be diverted to the standby - * port by the BE's ARM firmware (assuming the standby port has link). In - * this case, the standy port assumes the active status. Note: when link is - * restored on the failed port, traffic continues on the currently active - * port. The ARM firmware does not attempt to 'fail back' traffic to - * the restored port. - */ -struct BE_ASYNC_EVENT_LINK_STATE_AMAP { - u8 port0_link_status[8]; - u8 port1_link_status[8]; - u8 active_port[8]; - u8 rsvd0[8]; /* DWORD 0 */ - u8 port0_duplex[8]; - u8 port0_speed[8]; - u8 port1_duplex[8]; - u8 port1_speed[8]; - u8 port0_fault[8]; - u8 port1_fault[8]; - u8 rsvd1[2][8]; /* DWORD 2 */ - struct BE_ASYNC_EVENT_TRAILER_AMAP trailer; -} __packed; -struct ASYNC_EVENT_LINK_STATE_AMAP { - u32 dw[4]; -}; -#endif /* __asyncmesg_amap_h__ */ diff --git a/drivers/staging/benet/be_cm.h b/drivers/staging/benet/be_cm.h deleted file mode 100644 index b7a1dfd20c36..000000000000 --- a/drivers/staging/benet/be_cm.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __be_cm_amap_h__ -#define __be_cm_amap_h__ -#include "be_common.h" -#include "etx_context.h" -#include "mpu_context.h" - -/* - * --- CEV_WATERMARK_ENUM --- - * CQ/EQ Watermark Encodings. Encoded as number of free entries in - * Queue when Watermark is reached. - */ -#define CEV_WMARK_0 (0) /* Watermark when Queue full */ -#define CEV_WMARK_16 (1) /* Watermark at 16 free entries */ -#define CEV_WMARK_32 (2) /* Watermark at 32 free entries */ -#define CEV_WMARK_48 (3) /* Watermark at 48 free entries */ -#define CEV_WMARK_64 (4) /* Watermark at 64 free entries */ -#define CEV_WMARK_80 (5) /* Watermark at 80 free entries */ -#define CEV_WMARK_96 (6) /* Watermark at 96 free entries */ -#define CEV_WMARK_112 (7) /* Watermark at 112 free entries */ -#define CEV_WMARK_128 (8) /* Watermark at 128 free entries */ -#define CEV_WMARK_144 (9) /* Watermark at 144 free entries */ -#define CEV_WMARK_160 (10) /* Watermark at 160 free entries */ -#define CEV_WMARK_176 (11) /* Watermark at 176 free entries */ -#define CEV_WMARK_192 (12) /* Watermark at 192 free entries */ -#define CEV_WMARK_208 (13) /* Watermark at 208 free entries */ -#define CEV_WMARK_224 (14) /* Watermark at 224 free entries */ -#define CEV_WMARK_240 (15) /* Watermark at 240 free entries */ - -/* - * --- CQ_CNT_ENUM --- - * Completion Queue Count Encodings. - */ -#define CEV_CQ_CNT_256 (0) /* CQ has 256 entries */ -#define CEV_CQ_CNT_512 (1) /* CQ has 512 entries */ -#define CEV_CQ_CNT_1024 (2) /* CQ has 1024 entries */ - -/* - * --- EQ_CNT_ENUM --- - * Event Queue Count Encodings. - */ -#define CEV_EQ_CNT_256 (0) /* EQ has 256 entries (16-byte EQEs only) */ -#define CEV_EQ_CNT_512 (1) /* EQ has 512 entries (16-byte EQEs only) */ -#define CEV_EQ_CNT_1024 (2) /* EQ has 1024 entries (4-byte or */ - /* 16-byte EQEs only) */ -#define CEV_EQ_CNT_2048 (3) /* EQ has 2048 entries (4-byte or */ - /* 16-byte EQEs only) */ -#define CEV_EQ_CNT_4096 (4) /* EQ has 4096 entries (4-byte EQEs only) */ - -/* - * --- EQ_SIZE_ENUM --- - * Event Queue Entry Size Encoding. - */ -#define CEV_EQ_SIZE_4 (0) /* EQE is 4 bytes */ -#define CEV_EQ_SIZE_16 (1) /* EQE is 16 bytes */ - -/* - * Completion Queue Context Table Entry. Contains the state of a CQ. - * Located in RAM within the CEV block. - */ -struct BE_CQ_CONTEXT_AMAP { - u8 Cidx[11]; /* DWORD 0 */ - u8 Watermark[4]; /* DWORD 0 */ - u8 NoDelay; /* DWORD 0 */ - u8 EPIdx[11]; /* DWORD 0 */ - u8 Count[2]; /* DWORD 0 */ - u8 valid; /* DWORD 0 */ - u8 SolEvent; /* DWORD 0 */ - u8 Eventable; /* DWORD 0 */ - u8 Pidx[11]; /* DWORD 1 */ - u8 PD[10]; /* DWORD 1 */ - u8 EQID[7]; /* DWORD 1 */ - u8 Func; /* DWORD 1 */ - u8 WME; /* DWORD 1 */ - u8 Stalled; /* DWORD 1 */ - u8 Armed; /* DWORD 1 */ -} __packed; -struct CQ_CONTEXT_AMAP { - u32 dw[2]; -}; - -/* - * Event Queue Context Table Entry. Contains the state of an EQ. - * Located in RAM in the CEV block. - */ -struct BE_EQ_CONTEXT_AMAP { - u8 Cidx[13]; /* DWORD 0 */ - u8 rsvd0[2]; /* DWORD 0 */ - u8 Func; /* DWORD 0 */ - u8 EPIdx[13]; /* DWORD 0 */ - u8 valid; /* DWORD 0 */ - u8 rsvd1; /* DWORD 0 */ - u8 Size; /* DWORD 0 */ - u8 Pidx[13]; /* DWORD 1 */ - u8 rsvd2[3]; /* DWORD 1 */ - u8 PD[10]; /* DWORD 1 */ - u8 Count[3]; /* DWORD 1 */ - u8 SolEvent; /* DWORD 1 */ - u8 Stalled; /* DWORD 1 */ - u8 Armed; /* DWORD 1 */ - u8 Watermark[4]; /* DWORD 2 */ - u8 WME; /* DWORD 2 */ - u8 rsvd3[3]; /* DWORD 2 */ - u8 EventVect[6]; /* DWORD 2 */ - u8 rsvd4[2]; /* DWORD 2 */ - u8 Delay[8]; /* DWORD 2 */ - u8 rsvd5[6]; /* DWORD 2 */ - u8 TMR; /* DWORD 2 */ - u8 rsvd6; /* DWORD 2 */ - u8 rsvd7[32]; /* DWORD 3 */ -} __packed; -struct EQ_CONTEXT_AMAP { - u32 dw[4]; -}; - -#endif /* __be_cm_amap_h__ */ diff --git a/drivers/staging/benet/be_common.h b/drivers/staging/benet/be_common.h deleted file mode 100644 index 7e63dc5e3348..000000000000 --- a/drivers/staging/benet/be_common.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __be_common_amap_h__ -#define __be_common_amap_h__ - -/* Physical Address. */ -struct BE_PHYS_ADDR_AMAP { - u8 lo[32]; /* DWORD 0 */ - u8 hi[32]; /* DWORD 1 */ -} __packed; -struct PHYS_ADDR_AMAP { - u32 dw[2]; -}; - -/* Virtual Address. */ -struct BE_VIRT_ADDR_AMAP { - u8 lo[32]; /* DWORD 0 */ - u8 hi[32]; /* DWORD 1 */ -} __packed; -struct VIRT_ADDR_AMAP { - u32 dw[2]; -}; - -/* Scatter gather element. */ -struct BE_SGE_AMAP { - u8 addr_hi[32]; /* DWORD 0 */ - u8 addr_lo[32]; /* DWORD 1 */ - u8 rsvd0[32]; /* DWORD 2 */ - u8 len[16]; /* DWORD 3 */ - u8 rsvd1[16]; /* DWORD 3 */ -} __packed; -struct SGE_AMAP { - u32 dw[4]; -}; - -#endif /* __be_common_amap_h__ */ diff --git a/drivers/staging/benet/be_ethtool.c b/drivers/staging/benet/be_ethtool.c deleted file mode 100644 index 027af85707aa..000000000000 --- a/drivers/staging/benet/be_ethtool.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * be_ethtool.c - * - * This file contains various functions that ethtool can use - * to talk to the driver and the BE H/W. - */ - -#include "benet.h" - -#include - -static const char benet_gstrings_stats[][ETH_GSTRING_LEN] = { -/* net_device_stats */ - "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", - "rx_frame_errors", - "rx_fifo_errors", - "rx_missed_errors", - "tx_aborted_errors", - "tx_carrier_errors", - "tx_fifo_errors", - "tx_heartbeat_errors", - "tx_window_errors", - "rx_compressed", - "tc_compressed", -/* BE driver Stats */ - "bes_tx_reqs", - "bes_tx_fails", - "bes_fwd_reqs", - "bes_tx_wrbs", - "bes_interrupts", - "bes_events", - "bes_tx_events", - "bes_rx_events", - "bes_tx_compl", - "bes_rx_compl", - "bes_ethrx_post_fail", - "bes_802_3_dropped_frames", - "bes_802_3_malformed_frames", - "bes_rx_misc_pkts", - "bes_eth_tx_rate", - "bes_eth_rx_rate", - "Num Packets collected", - "Num Times Flushed", -}; - -#define NET_DEV_STATS_LEN \ - (sizeof(struct net_device_stats)/sizeof(unsigned long)) - -#define BENET_STATS_LEN ARRAY_SIZE(benet_gstrings_stats) - -static void -be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - strncpy(drvinfo->driver, be_driver_name, 32); - strncpy(drvinfo->version, be_drvr_ver, 32); - strncpy(drvinfo->fw_version, be_fw_ver, 32); - strcpy(drvinfo->bus_info, pci_name(adapter->pdev)); - drvinfo->testinfo_len = 0; - drvinfo->regdump_len = 0; - drvinfo->eedump_len = 0; -} - -static int -be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - coalesce->rx_max_coalesced_frames = adapter->max_rx_coal; - - coalesce->rx_coalesce_usecs = adapter->cur_eqd; - coalesce->rx_coalesce_usecs_high = adapter->max_eqd; - coalesce->rx_coalesce_usecs_low = adapter->min_eqd; - - coalesce->tx_coalesce_usecs = adapter->cur_eqd; - coalesce->tx_coalesce_usecs_high = adapter->max_eqd; - coalesce->tx_coalesce_usecs_low = adapter->min_eqd; - - coalesce->use_adaptive_rx_coalesce = adapter->enable_aic; - coalesce->use_adaptive_tx_coalesce = adapter->enable_aic; - - return 0; -} - -/* - * This routine is used to set interrup coalescing delay *as well as* - * the number of pkts to coalesce for LRO. - */ -static int -be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - struct be_eq_object *eq_objectp; - u32 max, min, cur; - int status; - - adapter->max_rx_coal = coalesce->rx_max_coalesced_frames; - if (adapter->max_rx_coal >= BE_LRO_MAX_PKTS) - adapter->max_rx_coal = BE_LRO_MAX_PKTS; - - if (adapter->enable_aic == 0 && - coalesce->use_adaptive_rx_coalesce == 1) { - /* if AIC is being turned on now, start with an EQD of 0 */ - adapter->cur_eqd = 0; - } - adapter->enable_aic = coalesce->use_adaptive_rx_coalesce; - - /* round off to nearest multiple of 8 */ - max = (((coalesce->rx_coalesce_usecs_high + 4) >> 3) << 3); - min = (((coalesce->rx_coalesce_usecs_low + 4) >> 3) << 3); - cur = (((coalesce->rx_coalesce_usecs + 4) >> 3) << 3); - - if (adapter->enable_aic) { - /* accept low and high if AIC is enabled */ - if (max > MAX_EQD) - max = MAX_EQD; - if (min > max) - min = max; - adapter->max_eqd = max; - adapter->min_eqd = min; - if (adapter->cur_eqd > max) - adapter->cur_eqd = max; - if (adapter->cur_eqd < min) - adapter->cur_eqd = min; - } else { - /* accept specified coalesce_usecs only if AIC is disabled */ - if (cur > MAX_EQD) - cur = MAX_EQD; - eq_objectp = &pnob->event_q_obj; - status = - be_eq_modify_delay(&pnob->fn_obj, 1, &eq_objectp, &cur, - NULL, NULL, NULL); - if (status == BE_SUCCESS) - adapter->cur_eqd = cur; - } - return 0; -} - -static u32 be_get_rx_csum(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - return adapter->rx_csum; -} - -static int be_set_rx_csum(struct net_device *netdev, uint32_t data) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - if (data) - adapter->rx_csum = 1; - else - adapter->rx_csum = 0; - - return 0; -} - -static void -be_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) -{ - switch (stringset) { - case ETH_SS_STATS: - memcpy(data, *benet_gstrings_stats, - sizeof(benet_gstrings_stats)); - break; - } -} - -static int be_get_stats_count(struct net_device *netdev) -{ - return BENET_STATS_LEN; -} - -static void -be_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, uint64_t *data) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - int i; - - benet_get_stats(netdev); - - for (i = 0; i <= NET_DEV_STATS_LEN; i++) - data[i] = ((unsigned long *)&adapter->benet_stats)[i]; - - data[i] = adapter->be_stat.bes_tx_reqs; - data[i++] = adapter->be_stat.bes_tx_fails; - data[i++] = adapter->be_stat.bes_fwd_reqs; - data[i++] = adapter->be_stat.bes_tx_wrbs; - - data[i++] = adapter->be_stat.bes_ints; - data[i++] = adapter->be_stat.bes_events; - data[i++] = adapter->be_stat.bes_tx_events; - data[i++] = adapter->be_stat.bes_rx_events; - data[i++] = adapter->be_stat.bes_tx_compl; - data[i++] = adapter->be_stat.bes_rx_compl; - data[i++] = adapter->be_stat.bes_ethrx_post_fail; - data[i++] = adapter->be_stat.bes_802_3_dropped_frames; - data[i++] = adapter->be_stat.bes_802_3_malformed_frames; - data[i++] = adapter->be_stat.bes_rx_misc_pkts; - data[i++] = adapter->be_stat.bes_eth_tx_rate; - data[i++] = adapter->be_stat.bes_eth_rx_rate; - data[i++] = adapter->be_stat.bes_rx_coal; - data[i++] = adapter->be_stat.bes_rx_flush; - -} - -static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) -{ - ecmd->speed = SPEED_10000; - ecmd->duplex = DUPLEX_FULL; - ecmd->autoneg = AUTONEG_DISABLE; - return 0; -} - -/* Get the Ring parameters from the pnob */ -static void -be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - /* Pre Set Maxims */ - ring->rx_max_pending = pnob->rx_q_len; - ring->rx_mini_max_pending = ring->rx_mini_max_pending; - ring->rx_jumbo_max_pending = ring->rx_jumbo_max_pending; - ring->tx_max_pending = pnob->tx_q_len; - - /* Current hardware Settings */ - ring->rx_pending = atomic_read(&pnob->rx_q_posted); - ring->rx_mini_pending = ring->rx_mini_pending; - ring->rx_jumbo_pending = ring->rx_jumbo_pending; - ring->tx_pending = atomic_read(&pnob->tx_q_used); - -} - -static void -be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) -{ - struct be_net_object *pnob = netdev_priv(netdev); - bool rxfc, txfc; - int status; - - status = be_eth_get_flow_control(&pnob->fn_obj, &txfc, &rxfc); - if (status != BE_SUCCESS) { - dev_info(&netdev->dev, "Unable to get pause frame settings\n"); - /* return defaults */ - ecmd->rx_pause = 1; - ecmd->tx_pause = 0; - ecmd->autoneg = AUTONEG_ENABLE; - return; - } - - if (txfc == true) - ecmd->tx_pause = 1; - else - ecmd->tx_pause = 0; - - if (rxfc == true) - ecmd->rx_pause = 1; - else - ecmd->rx_pause = 0; - - ecmd->autoneg = AUTONEG_ENABLE; -} - -static int -be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) -{ - struct be_net_object *pnob = netdev_priv(netdev); - bool txfc, rxfc; - int status; - - if (ecmd->autoneg != AUTONEG_ENABLE) - return -EINVAL; - - if (ecmd->tx_pause) - txfc = true; - else - txfc = false; - - if (ecmd->rx_pause) - rxfc = true; - else - rxfc = false; - - status = be_eth_set_flow_control(&pnob->fn_obj, txfc, rxfc); - if (status != BE_SUCCESS) { - dev_info(&netdev->dev, "Unable to set pause frame settings\n"); - return -1; - } - return 0; -} - -struct ethtool_ops be_ethtool_ops = { - .get_settings = be_get_settings, - .get_drvinfo = be_get_drvinfo, - .get_link = ethtool_op_get_link, - .get_coalesce = be_get_coalesce, - .set_coalesce = be_set_coalesce, - .get_ringparam = be_get_ringparam, - .get_pauseparam = be_get_pauseparam, - .set_pauseparam = be_set_pauseparam, - .get_rx_csum = be_get_rx_csum, - .set_rx_csum = be_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, - .get_strings = be_get_strings, - .get_stats_count = be_get_stats_count, - .get_ethtool_stats = be_get_ethtool_stats, -}; diff --git a/drivers/staging/benet/be_init.c b/drivers/staging/benet/be_init.c deleted file mode 100644 index 12a026c3f9e1..000000000000 --- a/drivers/staging/benet/be_init.c +++ /dev/null @@ -1,1382 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include -#include "benet.h" - -#define DRVR_VERSION "1.0.728" - -static const struct pci_device_id be_device_id_table[] = { - {PCI_DEVICE(0x19a2, 0x0201)}, - {0} -}; - -MODULE_DEVICE_TABLE(pci, be_device_id_table); - -MODULE_VERSION(DRVR_VERSION); - -#define DRV_DESCRIPTION "ServerEngines BladeEngine Network Driver Version " - -MODULE_DESCRIPTION(DRV_DESCRIPTION DRVR_VERSION); -MODULE_AUTHOR("ServerEngines"); -MODULE_LICENSE("GPL"); - -static unsigned int msix = 1; -module_param(msix, uint, S_IRUGO); -MODULE_PARM_DESC(msix, "Use MSI-x interrupts"); - -static unsigned int rxbuf_size = 2048; /* Default RX frag size */ -module_param(rxbuf_size, uint, S_IRUGO); -MODULE_PARM_DESC(rxbuf_size, "Size of buffers to hold Rx data"); - -const char be_drvr_ver[] = DRVR_VERSION; -char be_fw_ver[32]; /* F/W version filled in by be_probe */ -char be_driver_name[] = "benet"; - -/* - * Number of entries in each queue. - */ -#define EVENT_Q_LEN 1024 -#define ETH_TXQ_LEN 2048 -#define ETH_TXCQ_LEN 1024 -#define ETH_RXQ_LEN 1024 /* Does not support any other value */ -#define ETH_UC_RXCQ_LEN 1024 -#define ETH_BC_RXCQ_LEN 256 -#define MCC_Q_LEN 64 /* total size not to exceed 8 pages */ -#define MCC_CQ_LEN 256 - -/* Bit mask describing events of interest to be traced */ -unsigned int trace_level; - -static int -init_pci_be_function(struct be_adapter *adapter, struct pci_dev *pdev) -{ - u64 pa; - - /* CSR */ - pa = pci_resource_start(pdev, 2); - adapter->csr_va = ioremap_nocache(pa, pci_resource_len(pdev, 2)); - if (adapter->csr_va == NULL) - return -ENOMEM; - - /* Door Bell */ - pa = pci_resource_start(pdev, 4); - adapter->db_va = ioremap_nocache(pa, (128 * 1024)); - if (adapter->db_va == NULL) { - iounmap(adapter->csr_va); - return -ENOMEM; - } - - /* PCI */ - pa = pci_resource_start(pdev, 1); - adapter->pci_va = ioremap_nocache(pa, pci_resource_len(pdev, 1)); - if (adapter->pci_va == NULL) { - iounmap(adapter->csr_va); - iounmap(adapter->db_va); - return -ENOMEM; - } - return 0; -} - -/* - This function enables the interrupt corresponding to the Event - queue ID for the given NetObject -*/ -void be_enable_eq_intr(struct be_net_object *pnob) -{ - struct CQ_DB_AMAP cqdb; - cqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(CQ_DB, event, &cqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, 0); - AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, pnob->event_q_id); - PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]); -} - -/* - This function disables the interrupt corresponding to the Event - queue ID for the given NetObject -*/ -void be_disable_eq_intr(struct be_net_object *pnob) -{ - struct CQ_DB_AMAP cqdb; - cqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(CQ_DB, event, &cqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, 0); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, 0); - AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, pnob->event_q_id); - PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]); -} - -/* - This function enables the interrupt from the network function - of the BladeEngine. Use the function be_disable_eq_intr() - to enable the interrupt from the event queue of only one specific - NetObject -*/ -void be_enable_intr(struct be_net_object *pnob) -{ - struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl; - u32 host_intr; - - ctrl.dw[0] = PCICFG1_READ(&pnob->fn_obj, host_timer_int_ctrl); - host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw); - if (!host_intr) { - AMAP_SET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw, 1); - PCICFG1_WRITE(&pnob->fn_obj, host_timer_int_ctrl, - ctrl.dw[0]); - } -} - -/* - This function disables the interrupt from the network function of - the BladeEngine. Use the function be_disable_eq_intr() to - disable the interrupt from the event queue of only one specific NetObject -*/ -void be_disable_intr(struct be_net_object *pnob) -{ - - struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl; - u32 host_intr; - ctrl.dw[0] = PCICFG1_READ(&pnob->fn_obj, host_timer_int_ctrl); - host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw); - if (host_intr) { - AMAP_SET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, hostintr, - ctrl.dw, 0); - PCICFG1_WRITE(&pnob->fn_obj, host_timer_int_ctrl, - ctrl.dw[0]); - } -} - -static int be_enable_msix(struct be_adapter *adapter) -{ - int i, ret; - - if (!msix) - return -1; - - for (i = 0; i < BE_MAX_REQ_MSIX_VECTORS; i++) - adapter->msix_entries[i].entry = i; - - ret = pci_enable_msix(adapter->pdev, adapter->msix_entries, - BE_MAX_REQ_MSIX_VECTORS); - - if (ret == 0) - adapter->msix_enabled = 1; - return ret; -} - -static int be_register_isr(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - struct net_device *netdev = pnob->netdev; - int intx = 0, r; - - netdev->irq = adapter->pdev->irq; - r = be_enable_msix(adapter); - - if (r == 0) { - r = request_irq(adapter->msix_entries[0].vector, - be_int, IRQF_SHARED, netdev->name, netdev); - if (r) { - printk(KERN_WARNING - "MSIX Request IRQ failed - Errno %d\n", r); - intx = 1; - pci_disable_msix(adapter->pdev); - adapter->msix_enabled = 0; - } - } else { - intx = 1; - } - - if (intx) { - r = request_irq(netdev->irq, be_int, IRQF_SHARED, - netdev->name, netdev); - if (r) { - printk(KERN_WARNING - "INTx Request IRQ failed - Errno %d\n", r); - return -1; - } - } - adapter->isr_registered = 1; - return 0; -} - -static void be_unregister_isr(struct be_adapter *adapter) -{ - struct net_device *netdev = adapter->netdevp; - if (adapter->isr_registered) { - if (adapter->msix_enabled) { - free_irq(adapter->msix_entries[0].vector, netdev); - pci_disable_msix(adapter->pdev); - adapter->msix_enabled = 0; - } else { - free_irq(netdev->irq, netdev); - } - adapter->isr_registered = 0; - } -} - -/* - This function processes the Flush Completions that are issued by the - ARM F/W, when a Recv Ring is destroyed. A flush completion is - identified when a Rx COmpl descriptor has the tcpcksum and udpcksum - set and the pktsize is 32. These completions are received on the - Rx Completion Queue. -*/ -static u32 be_process_rx_flush_cmpl(struct be_net_object *pnob) -{ - struct ETH_RX_COMPL_AMAP *rxcp; - unsigned int i = 0; - while ((rxcp = be_get_rx_cmpl(pnob)) != NULL) { - be_notify_cmpl(pnob, 1, pnob->rx_cq_id, 1); - i++; - } - return i; -} - -static void be_tx_q_clean(struct be_net_object *pnob) -{ - while (atomic_read(&pnob->tx_q_used)) - process_one_tx_compl(pnob, tx_compl_lastwrb_idx_get(pnob)); -} - -static void be_rx_q_clean(struct be_net_object *pnob) -{ - if (pnob->rx_ctxt) { - int i; - struct be_rx_page_info *rx_page_info; - for (i = 0; i < pnob->rx_q_len; i++) { - rx_page_info = &(pnob->rx_page_info[i]); - if (!pnob->rx_pg_shared || rx_page_info->page_offset) { - pci_unmap_page(pnob->adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - pnob->rx_buf_size, - PCI_DMA_FROMDEVICE); - } - if (rx_page_info->page) - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - } - pnob->rx_pg_info_hd = 0; - } -} - -static void be_destroy_netobj(struct be_net_object *pnob) -{ - int status; - - if (pnob->tx_q_created) { - status = be_eth_sq_destroy(&pnob->tx_q_obj); - pnob->tx_q_created = 0; - } - - if (pnob->rx_q_created) { - status = be_eth_rq_destroy(&pnob->rx_q_obj); - if (status != 0) { - status = be_eth_rq_destroy_options(&pnob->rx_q_obj, 0, - NULL, NULL); - BUG_ON(status); - } - pnob->rx_q_created = 0; - } - - be_process_rx_flush_cmpl(pnob); - - if (pnob->tx_cq_created) { - status = be_cq_destroy(&pnob->tx_cq_obj); - pnob->tx_cq_created = 0; - } - - if (pnob->rx_cq_created) { - status = be_cq_destroy(&pnob->rx_cq_obj); - pnob->rx_cq_created = 0; - } - - if (pnob->mcc_q_created) { - status = be_mcc_ring_destroy(&pnob->mcc_q_obj); - pnob->mcc_q_created = 0; - } - if (pnob->mcc_cq_created) { - status = be_cq_destroy(&pnob->mcc_cq_obj); - pnob->mcc_cq_created = 0; - } - - if (pnob->event_q_created) { - status = be_eq_destroy(&pnob->event_q_obj); - pnob->event_q_created = 0; - } - be_function_cleanup(&pnob->fn_obj); -} - -/* - * free all resources associated with a pnob - * Called at the time of module cleanup as well a any error during - * module init. Some resources may be partially allocated in a NetObj. - */ -static void netobject_cleanup(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - struct net_device *netdev = adapter->netdevp; - - if (netif_running(netdev)) { - netif_stop_queue(netdev); - be_wait_nic_tx_cmplx_cmpl(pnob); - be_disable_eq_intr(pnob); - } - - be_unregister_isr(adapter); - - if (adapter->tasklet_started) { - tasklet_kill(&(adapter->sts_handler)); - adapter->tasklet_started = 0; - } - if (pnob->fn_obj_created) - be_disable_intr(pnob); - - if (adapter->dev_state != BE_DEV_STATE_NONE) - unregister_netdev(netdev); - - if (pnob->fn_obj_created) - be_destroy_netobj(pnob); - - adapter->net_obj = NULL; - adapter->netdevp = NULL; - - be_rx_q_clean(pnob); - if (pnob->rx_ctxt) { - kfree(pnob->rx_page_info); - kfree(pnob->rx_ctxt); - } - - be_tx_q_clean(pnob); - kfree(pnob->tx_ctxt); - - if (pnob->mcc_q) - pci_free_consistent(adapter->pdev, pnob->mcc_q_size, - pnob->mcc_q, pnob->mcc_q_bus); - - if (pnob->mcc_wrb_ctxt) - free_pages((unsigned long)pnob->mcc_wrb_ctxt, - get_order(pnob->mcc_wrb_ctxt_size)); - - if (pnob->mcc_cq) - pci_free_consistent(adapter->pdev, pnob->mcc_cq_size, - pnob->mcc_cq, pnob->mcc_cq_bus); - - if (pnob->event_q) - pci_free_consistent(adapter->pdev, pnob->event_q_size, - pnob->event_q, pnob->event_q_bus); - - if (pnob->tx_cq) - pci_free_consistent(adapter->pdev, pnob->tx_cq_size, - pnob->tx_cq, pnob->tx_cq_bus); - - if (pnob->tx_q) - pci_free_consistent(adapter->pdev, pnob->tx_q_size, - pnob->tx_q, pnob->tx_q_bus); - - if (pnob->rx_q) - pci_free_consistent(adapter->pdev, pnob->rx_q_size, - pnob->rx_q, pnob->rx_q_bus); - - if (pnob->rx_cq) - pci_free_consistent(adapter->pdev, pnob->rx_cq_size, - pnob->rx_cq, pnob->rx_cq_bus); - - - if (pnob->mb_ptr) - pci_free_consistent(adapter->pdev, pnob->mb_size, pnob->mb_ptr, - pnob->mb_bus); - - free_netdev(netdev); -} - - -static int be_nob_ring_alloc(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - u32 size; - - /* Mail box rd; mailbox pointer needs to be 16 byte aligned */ - pnob->mb_size = sizeof(struct MCC_MAILBOX_AMAP) + 16; - pnob->mb_ptr = pci_alloc_consistent(adapter->pdev, pnob->mb_size, - &pnob->mb_bus); - if (!pnob->mb_bus) - return -1; - memset(pnob->mb_ptr, 0, pnob->mb_size); - pnob->mb_rd.va = PTR_ALIGN(pnob->mb_ptr, 16); - pnob->mb_rd.pa = PTR_ALIGN(pnob->mb_bus, 16); - pnob->mb_rd.length = sizeof(struct MCC_MAILBOX_AMAP); - /* - * Event queue - */ - pnob->event_q_len = EVENT_Q_LEN; - pnob->event_q_size = pnob->event_q_len * sizeof(struct EQ_ENTRY_AMAP); - pnob->event_q = pci_alloc_consistent(adapter->pdev, pnob->event_q_size, - &pnob->event_q_bus); - if (!pnob->event_q_bus) - return -1; - memset(pnob->event_q, 0, pnob->event_q_size); - /* - * Eth TX queue - */ - pnob->tx_q_len = ETH_TXQ_LEN; - pnob->tx_q_port = 0; - pnob->tx_q_size = pnob->tx_q_len * sizeof(struct ETH_WRB_AMAP); - pnob->tx_q = pci_alloc_consistent(adapter->pdev, pnob->tx_q_size, - &pnob->tx_q_bus); - if (!pnob->tx_q_bus) - return -1; - memset(pnob->tx_q, 0, pnob->tx_q_size); - /* - * Eth TX Compl queue - */ - pnob->txcq_len = ETH_TXCQ_LEN; - pnob->tx_cq_size = pnob->txcq_len * sizeof(struct ETH_TX_COMPL_AMAP); - pnob->tx_cq = pci_alloc_consistent(adapter->pdev, pnob->tx_cq_size, - &pnob->tx_cq_bus); - if (!pnob->tx_cq_bus) - return -1; - memset(pnob->tx_cq, 0, pnob->tx_cq_size); - /* - * Eth RX queue - */ - pnob->rx_q_len = ETH_RXQ_LEN; - pnob->rx_q_size = pnob->rx_q_len * sizeof(struct ETH_RX_D_AMAP); - pnob->rx_q = pci_alloc_consistent(adapter->pdev, pnob->rx_q_size, - &pnob->rx_q_bus); - if (!pnob->rx_q_bus) - return -1; - memset(pnob->rx_q, 0, pnob->rx_q_size); - /* - * Eth Unicast RX Compl queue - */ - pnob->rx_cq_len = ETH_UC_RXCQ_LEN; - pnob->rx_cq_size = pnob->rx_cq_len * - sizeof(struct ETH_RX_COMPL_AMAP); - pnob->rx_cq = pci_alloc_consistent(adapter->pdev, pnob->rx_cq_size, - &pnob->rx_cq_bus); - if (!pnob->rx_cq_bus) - return -1; - memset(pnob->rx_cq, 0, pnob->rx_cq_size); - - /* TX resources */ - size = pnob->tx_q_len * sizeof(void **); - pnob->tx_ctxt = kzalloc(size, GFP_KERNEL); - if (pnob->tx_ctxt == NULL) - return -1; - - /* RX resources */ - size = pnob->rx_q_len * sizeof(void *); - pnob->rx_ctxt = kzalloc(size, GFP_KERNEL); - if (pnob->rx_ctxt == NULL) - return -1; - - size = (pnob->rx_q_len * sizeof(struct be_rx_page_info)); - pnob->rx_page_info = kzalloc(size, GFP_KERNEL); - if (pnob->rx_page_info == NULL) - return -1; - - adapter->eth_statsp = kzalloc(sizeof(struct FWCMD_ETH_GET_STATISTICS), - GFP_KERNEL); - if (adapter->eth_statsp == NULL) - return -1; - pnob->rx_buf_size = rxbuf_size; - return 0; -} - -/* - This function initializes the be_net_object for subsequent - network operations. - - Before calling this function, the driver must have allocated - space for the NetObject structure, initialized the structure, - allocated DMAable memory for all the network queues that form - part of the NetObject and populated the start address (virtual) - and number of entries allocated for each queue in the NetObject structure. - - The driver must also have allocated memory to hold the - mailbox structure (MCC_MAILBOX) and post the physical address, - virtual addresses and the size of the mailbox memory in the - NetObj.mb_rd. This structure is used by BECLIB for - initial communication with the embedded MCC processor. BECLIB - uses the mailbox until MCC rings are created for more efficient - communication with the MCC processor. - - If the driver wants to create multiple network interface for more - than one protection domain, it can call be_create_netobj() - multiple times once for each protection domain. A Maximum of - 32 protection domains are supported. - -*/ -static int -be_create_netobj(struct be_net_object *pnob, u8 __iomem *csr_va, - u8 __iomem *db_va, u8 __iomem *pci_va) -{ - int status = 0; - bool eventable = false, tx_no_delay = false, rx_no_delay = false; - struct be_eq_object *eq_objectp = NULL; - struct be_function_object *pfob = &pnob->fn_obj; - struct ring_desc rd; - u32 set_rxbuf_size; - u32 tx_cmpl_wm = CEV_WMARK_96; /* 0xffffffff to disable */ - u32 rx_cmpl_wm = CEV_WMARK_160; /* 0xffffffff to disable */ - u32 eq_delay = 0; /* delay in 8usec units. 0xffffffff to disable */ - - memset(&rd, 0, sizeof(struct ring_desc)); - - status = be_function_object_create(csr_va, db_va, pci_va, - BE_FUNCTION_TYPE_NETWORK, &pnob->mb_rd, pfob); - if (status != BE_SUCCESS) - return status; - pnob->fn_obj_created = true; - - if (tx_cmpl_wm == 0xffffffff) - tx_no_delay = true; - if (rx_cmpl_wm == 0xffffffff) - rx_no_delay = true; - /* - * now create the necessary rings - * Event Queue first. - */ - if (pnob->event_q_len) { - rd.va = pnob->event_q; - rd.pa = pnob->event_q_bus; - rd.length = pnob->event_q_size; - - status = be_eq_create(pfob, &rd, 4, pnob->event_q_len, - (u32) -1, /* CEV_WMARK_* or -1 */ - eq_delay, /* in 8us units, or -1 */ - &pnob->event_q_obj); - if (status != BE_SUCCESS) - goto error_ret; - pnob->event_q_id = pnob->event_q_obj.eq_id; - pnob->event_q_created = 1; - eventable = true; - eq_objectp = &pnob->event_q_obj; - } - /* - * Now Eth Tx Compl. queue. - */ - if (pnob->txcq_len) { - rd.va = pnob->tx_cq; - rd.pa = pnob->tx_cq_bus; - rd.length = pnob->tx_cq_size; - - status = be_cq_create(pfob, &rd, - pnob->txcq_len * sizeof(struct ETH_TX_COMPL_AMAP), - false, /* solicted events, */ - tx_no_delay, /* nodelay */ - tx_cmpl_wm, /* Watermark encodings */ - eq_objectp, &pnob->tx_cq_obj); - if (status != BE_SUCCESS) - goto error_ret; - - pnob->tx_cq_id = pnob->tx_cq_obj.cq_id; - pnob->tx_cq_created = 1; - } - /* - * Eth Tx queue - */ - if (pnob->tx_q_len) { - struct be_eth_sq_parameters ex_params = { 0 }; - u32 type; - - if (pnob->tx_q_port) { - /* TXQ to be bound to a specific port */ - type = BE_ETH_TX_RING_TYPE_BOUND; - ex_params.port = pnob->tx_q_port - 1; - } else - type = BE_ETH_TX_RING_TYPE_STANDARD; - - rd.va = pnob->tx_q; - rd.pa = pnob->tx_q_bus; - rd.length = pnob->tx_q_size; - - status = be_eth_sq_create_ex(pfob, &rd, - pnob->tx_q_len * sizeof(struct ETH_WRB_AMAP), - type, 2, &pnob->tx_cq_obj, - &ex_params, &pnob->tx_q_obj); - - if (status != BE_SUCCESS) - goto error_ret; - - pnob->tx_q_id = pnob->tx_q_obj.bid; - pnob->tx_q_created = 1; - } - /* - * Now Eth Rx compl. queue. Always needed. - */ - rd.va = pnob->rx_cq; - rd.pa = pnob->rx_cq_bus; - rd.length = pnob->rx_cq_size; - - status = be_cq_create(pfob, &rd, - pnob->rx_cq_len * sizeof(struct ETH_RX_COMPL_AMAP), - false, /* solicted events, */ - rx_no_delay, /* nodelay */ - rx_cmpl_wm, /* Watermark encodings */ - eq_objectp, &pnob->rx_cq_obj); - if (status != BE_SUCCESS) - goto error_ret; - - pnob->rx_cq_id = pnob->rx_cq_obj.cq_id; - pnob->rx_cq_created = 1; - - status = be_eth_rq_set_frag_size(pfob, pnob->rx_buf_size, - (u32 *) &set_rxbuf_size); - if (status != BE_SUCCESS) { - be_eth_rq_get_frag_size(pfob, (u32 *) &pnob->rx_buf_size); - if ((pnob->rx_buf_size != 2048) && (pnob->rx_buf_size != 4096) - && (pnob->rx_buf_size != 8192)) - goto error_ret; - } else { - if (pnob->rx_buf_size != set_rxbuf_size) - pnob->rx_buf_size = set_rxbuf_size; - } - /* - * Eth RX queue. be_eth_rq_create() always assumes 2 pages size - */ - rd.va = pnob->rx_q; - rd.pa = pnob->rx_q_bus; - rd.length = pnob->rx_q_size; - - status = be_eth_rq_create(pfob, &rd, &pnob->rx_cq_obj, - &pnob->rx_cq_obj, &pnob->rx_q_obj); - - if (status != BE_SUCCESS) - goto error_ret; - - pnob->rx_q_id = pnob->rx_q_obj.rid; - pnob->rx_q_created = 1; - - return BE_SUCCESS; /* All required queues created. */ - -error_ret: - be_destroy_netobj(pnob); - return status; -} - -static int be_nob_ring_init(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - int status; - - pnob->event_q_tl = 0; - - pnob->tx_q_hd = 0; - pnob->tx_q_tl = 0; - - pnob->tx_cq_tl = 0; - - pnob->rx_cq_tl = 0; - - memset(pnob->event_q, 0, pnob->event_q_size); - memset(pnob->tx_cq, 0, pnob->tx_cq_size); - memset(pnob->tx_ctxt, 0, pnob->tx_q_len * sizeof(void **)); - memset(pnob->rx_ctxt, 0, pnob->rx_q_len * sizeof(void *)); - pnob->rx_pg_info_hd = 0; - pnob->rx_q_hd = 0; - atomic_set(&pnob->rx_q_posted, 0); - - status = be_create_netobj(pnob, adapter->csr_va, adapter->db_va, - adapter->pci_va); - if (status != BE_SUCCESS) - return -1; - - be_post_eth_rx_buffs(pnob); - return 0; -} - -/* This function handles async callback for link status */ -static void -be_link_status_async_callback(void *context, u32 event_code, void *event) -{ - struct ASYNC_EVENT_LINK_STATE_AMAP *link_status = event; - struct be_adapter *adapter = context; - bool link_enable = false; - struct be_net_object *pnob; - struct ASYNC_EVENT_TRAILER_AMAP *async_trailer; - struct net_device *netdev; - u32 async_event_code, async_event_type, active_port; - u32 port0_link_status, port1_link_status, port0_duplex, port1_duplex; - u32 port0_speed, port1_speed; - - if (event_code != ASYNC_EVENT_CODE_LINK_STATE) { - /* Not our event to handle */ - return; - } - async_trailer = (struct ASYNC_EVENT_TRAILER_AMAP *) - ((u8 *) event + sizeof(struct MCC_CQ_ENTRY_AMAP) - - sizeof(struct ASYNC_EVENT_TRAILER_AMAP)); - - async_event_code = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, event_code, - async_trailer); - BUG_ON(async_event_code != ASYNC_EVENT_CODE_LINK_STATE); - - pnob = adapter->net_obj; - netdev = pnob->netdev; - - /* Determine if this event is a switch VLD or a physical link event */ - async_event_type = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, event_type, - async_trailer); - active_port = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - active_port, link_status); - port0_link_status = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port0_link_status, link_status); - port1_link_status = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port1_link_status, link_status); - port0_duplex = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port0_duplex, link_status); - port1_duplex = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port1_duplex, link_status); - port0_speed = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port0_speed, link_status); - port1_speed = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port1_speed, link_status); - if (async_event_type == NTWK_LINK_TYPE_VIRTUAL) { - adapter->be_stat.bes_link_change_virtual++; - if (adapter->be_link_sts->active_port != active_port) { - dev_notice(&netdev->dev, - "Active port changed due to VLD on switch\n"); - } else { - dev_notice(&netdev->dev, "Link status update\n"); - } - - } else { - adapter->be_stat.bes_link_change_physical++; - if (adapter->be_link_sts->active_port != active_port) { - dev_notice(&netdev->dev, - "Active port changed due to port link" - " status change\n"); - } else { - dev_notice(&netdev->dev, "Link status update\n"); - } - } - - memset(adapter->be_link_sts, 0, sizeof(adapter->be_link_sts)); - - if ((port0_link_status == ASYNC_EVENT_LINK_UP) || - (port1_link_status == ASYNC_EVENT_LINK_UP)) { - if ((adapter->port0_link_sts == BE_PORT_LINK_DOWN) && - (adapter->port1_link_sts == BE_PORT_LINK_DOWN)) { - /* Earlier both the ports are down So link is up */ - link_enable = true; - } - - if (port0_link_status == ASYNC_EVENT_LINK_UP) { - adapter->port0_link_sts = BE_PORT_LINK_UP; - adapter->be_link_sts->mac0_duplex = port0_duplex; - adapter->be_link_sts->mac0_speed = port0_speed; - if (active_port == NTWK_PORT_A) - adapter->be_link_sts->active_port = 0; - } else - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - - if (port1_link_status == ASYNC_EVENT_LINK_UP) { - adapter->port1_link_sts = BE_PORT_LINK_UP; - adapter->be_link_sts->mac1_duplex = port1_duplex; - adapter->be_link_sts->mac1_speed = port1_speed; - if (active_port == NTWK_PORT_B) - adapter->be_link_sts->active_port = 1; - } else - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - - printk(KERN_INFO "Link Properties for %s:\n", netdev->name); - dev_info(&netdev->dev, "Link Properties:\n"); - be_print_link_info(adapter->be_link_sts); - - if (!link_enable) - return; - /* - * Both ports were down previously, but atleast one of - * them has come up if this netdevice's carrier is not up, - * then indicate to stack - */ - if (!netif_carrier_ok(netdev)) { - netif_start_queue(netdev); - netif_carrier_on(netdev); - } - return; - } - - /* Now both the ports are down. Tell the stack about it */ - dev_info(&netdev->dev, "Both ports are down\n"); - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - if (netif_carrier_ok(netdev)) { - netif_carrier_off(netdev); - netif_stop_queue(netdev); - } - return; -} - -static int be_mcc_create(struct be_adapter *adapter) -{ - struct be_net_object *pnob; - - pnob = adapter->net_obj; - /* - * Create the MCC ring so that all further communication with - * MCC can go thru the ring. we do this at the end since - * we do not want to be dealing with interrupts until the - * initialization is complete. - */ - pnob->mcc_q_len = MCC_Q_LEN; - pnob->mcc_q_size = pnob->mcc_q_len * sizeof(struct MCC_WRB_AMAP); - pnob->mcc_q = pci_alloc_consistent(adapter->pdev, pnob->mcc_q_size, - &pnob->mcc_q_bus); - if (!pnob->mcc_q_bus) - return -1; - /* - * space for MCC WRB context - */ - pnob->mcc_wrb_ctxtLen = MCC_Q_LEN; - pnob->mcc_wrb_ctxt_size = pnob->mcc_wrb_ctxtLen * - sizeof(struct be_mcc_wrb_context); - pnob->mcc_wrb_ctxt = (void *)__get_free_pages(GFP_KERNEL, - get_order(pnob->mcc_wrb_ctxt_size)); - if (pnob->mcc_wrb_ctxt == NULL) - return -1; - /* - * Space for MCC compl. ring - */ - pnob->mcc_cq_len = MCC_CQ_LEN; - pnob->mcc_cq_size = pnob->mcc_cq_len * sizeof(struct MCC_CQ_ENTRY_AMAP); - pnob->mcc_cq = pci_alloc_consistent(adapter->pdev, pnob->mcc_cq_size, - &pnob->mcc_cq_bus); - if (!pnob->mcc_cq_bus) - return -1; - return 0; -} - -/* - This function creates the MCC request and completion ring required - for communicating with the ARM processor. The caller must have - allocated required amount of memory for the MCC ring and MCC - completion ring and posted the virtual address and number of - entries in the corresponding members (mcc_q and mcc_cq) in the - NetObject struture. - - When this call is completed, all further communication with - ARM will switch from mailbox to this ring. - - pnob - Pointer to the NetObject structure. This NetObject should - have been created using a previous call to be_create_netobj() -*/ -int be_create_mcc_rings(struct be_net_object *pnob) -{ - int status = 0; - struct ring_desc rd; - struct be_function_object *pfob = &pnob->fn_obj; - - memset(&rd, 0, sizeof(struct ring_desc)); - if (pnob->mcc_cq_len) { - rd.va = pnob->mcc_cq; - rd.pa = pnob->mcc_cq_bus; - rd.length = pnob->mcc_cq_size; - - status = be_cq_create(pfob, &rd, - pnob->mcc_cq_len * sizeof(struct MCC_CQ_ENTRY_AMAP), - false, /* solicted events, */ - true, /* nodelay */ - 0, /* 0 Watermark since Nodelay is true */ - &pnob->event_q_obj, - &pnob->mcc_cq_obj); - - if (status != BE_SUCCESS) - return status; - - pnob->mcc_cq_id = pnob->mcc_cq_obj.cq_id; - pnob->mcc_cq_created = 1; - } - if (pnob->mcc_q_len) { - rd.va = pnob->mcc_q; - rd.pa = pnob->mcc_q_bus; - rd.length = pnob->mcc_q_size; - - status = be_mcc_ring_create(pfob, &rd, - pnob->mcc_q_len * sizeof(struct MCC_WRB_AMAP), - pnob->mcc_wrb_ctxt, pnob->mcc_wrb_ctxtLen, - &pnob->mcc_cq_obj, &pnob->mcc_q_obj); - - if (status != BE_SUCCESS) - return status; - - pnob->mcc_q_created = 1; - } - return BE_SUCCESS; -} - -static int be_mcc_init(struct be_adapter *adapter) -{ - u32 r; - struct be_net_object *pnob; - - pnob = adapter->net_obj; - memset(pnob->mcc_q, 0, pnob->mcc_q_size); - pnob->mcc_q_hd = 0; - - memset(pnob->mcc_wrb_ctxt, 0, pnob->mcc_wrb_ctxt_size); - - memset(pnob->mcc_cq, 0, pnob->mcc_cq_size); - pnob->mcc_cq_tl = 0; - - r = be_create_mcc_rings(adapter->net_obj); - if (r != BE_SUCCESS) - return -1; - - return 0; -} - -static void be_remove(struct pci_dev *pdev) -{ - struct be_net_object *pnob; - struct be_adapter *adapter; - - adapter = pci_get_drvdata(pdev); - if (!adapter) - return; - - pci_set_drvdata(pdev, NULL); - pnob = (struct be_net_object *)adapter->net_obj; - - flush_scheduled_work(); - - if (pnob) { - /* Unregister async callback function for link status updates */ - if (pnob->mcc_q_created) - be_mcc_add_async_event_callback(&pnob->mcc_q_obj, - NULL, NULL); - netobject_cleanup(adapter, pnob); - } - - if (adapter->csr_va) - iounmap(adapter->csr_va); - if (adapter->db_va) - iounmap(adapter->db_va); - if (adapter->pci_va) - iounmap(adapter->pci_va); - - pci_release_regions(adapter->pdev); - pci_disable_device(adapter->pdev); - - kfree(adapter->be_link_sts); - kfree(adapter->eth_statsp); - - if (adapter->timer_ctxt.get_stats_timer.function) - del_timer_sync(&adapter->timer_ctxt.get_stats_timer); - kfree(adapter); -} - -/* - * This function is called by the PCI sub-system when it finds a PCI - * device with dev/vendor IDs that match with one of our devices. - * All of the driver initialization is done in this function. - */ -static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) -{ - int status = 0; - struct be_adapter *adapter; - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD get_fwv; - struct be_net_object *pnob; - struct net_device *netdev; - - status = pci_enable_device(pdev); - if (status) - goto error; - - status = pci_request_regions(pdev, be_driver_name); - if (status) - goto error_pci_req; - - pci_set_master(pdev); - adapter = kzalloc(sizeof(struct be_adapter), GFP_KERNEL); - if (adapter == NULL) { - status = -ENOMEM; - goto error_adapter; - } - adapter->dev_state = BE_DEV_STATE_NONE; - adapter->pdev = pdev; - pci_set_drvdata(pdev, adapter); - - adapter->enable_aic = 1; - adapter->max_eqd = MAX_EQD; - adapter->min_eqd = 0; - adapter->cur_eqd = 0; - - status = pci_set_dma_mask(pdev, DMA_64BIT_MASK); - if (!status) { - adapter->dma_64bit_cap = true; - } else { - adapter->dma_64bit_cap = false; - status = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (status != 0) { - printk(KERN_ERR "Could not set PCI DMA Mask\n"); - goto cleanup; - } - } - - status = init_pci_be_function(adapter, pdev); - if (status != 0) { - printk(KERN_ERR "Failed to map PCI BARS\n"); - status = -ENOMEM; - goto cleanup; - } - - be_trace_set_level(DL_ALWAYS | DL_ERR); - - adapter->be_link_sts = kmalloc(sizeof(struct BE_LINK_STATUS), - GFP_KERNEL); - if (adapter->be_link_sts == NULL) { - printk(KERN_ERR "Memory allocation for link status " - "buffer failed\n"); - goto cleanup; - } - spin_lock_init(&adapter->txq_lock); - - netdev = alloc_etherdev(sizeof(struct be_net_object)); - if (netdev == NULL) { - status = -ENOMEM; - goto cleanup; - } - pnob = netdev_priv(netdev); - adapter->net_obj = pnob; - adapter->netdevp = netdev; - pnob->adapter = adapter; - pnob->netdev = netdev; - - status = be_nob_ring_alloc(adapter, pnob); - if (status != 0) - goto cleanup; - - status = be_nob_ring_init(adapter, pnob); - if (status != 0) - goto cleanup; - - be_rxf_mac_address_read_write(&pnob->fn_obj, false, false, false, - false, false, netdev->dev_addr, NULL, NULL); - - netdev->init = &benet_init; - netif_carrier_off(netdev); - netif_stop_queue(netdev); - - SET_NETDEV_DEV(netdev, &(adapter->pdev->dev)); - - netif_napi_add(netdev, &pnob->napi, be_poll, 64); - - /* if the rx_frag size if 2K, one page is shared as two RX frags */ - pnob->rx_pg_shared = - (pnob->rx_buf_size <= PAGE_SIZE / 2) ? true : false; - if (pnob->rx_buf_size != rxbuf_size) { - printk(KERN_WARNING - "Could not set Rx buffer size to %d. Using %d\n", - rxbuf_size, pnob->rx_buf_size); - rxbuf_size = pnob->rx_buf_size; - } - - tasklet_init(&(adapter->sts_handler), be_process_intr, - (unsigned long)adapter); - adapter->tasklet_started = 1; - spin_lock_init(&(adapter->int_lock)); - - status = be_register_isr(adapter, pnob); - if (status != 0) - goto cleanup; - - adapter->rx_csum = 1; - adapter->max_rx_coal = BE_LRO_MAX_PKTS; - - memset(&get_fwv, 0, - sizeof(struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD)); - printk(KERN_INFO "BladeEngine Driver version:%s. " - "Copyright ServerEngines, Corporation 2005 - 2008\n", - be_drvr_ver); - status = be_function_get_fw_version(&pnob->fn_obj, &get_fwv, NULL, - NULL); - if (status == BE_SUCCESS) { - strncpy(be_fw_ver, get_fwv.firmware_version_string, 32); - printk(KERN_INFO "BladeEngine Firmware Version:%s\n", - get_fwv.firmware_version_string); - } else { - printk(KERN_WARNING "Unable to get BE Firmware Version\n"); - } - - sema_init(&adapter->get_eth_stat_sem, 0); - init_timer(&adapter->timer_ctxt.get_stats_timer); - atomic_set(&adapter->timer_ctxt.get_stat_flag, 0); - adapter->timer_ctxt.get_stats_timer.function = - &be_get_stats_timer_handler; - - status = be_mcc_create(adapter); - if (status < 0) - goto cleanup; - status = be_mcc_init(adapter); - if (status < 0) - goto cleanup; - - - status = be_mcc_add_async_event_callback(&adapter->net_obj->mcc_q_obj, - be_link_status_async_callback, (void *)adapter); - if (status != BE_SUCCESS) { - printk(KERN_WARNING "add_async_event_callback failed"); - printk(KERN_WARNING - "Link status changes may not be reflected\n"); - } - - status = register_netdev(netdev); - if (status != 0) - goto cleanup; - be_update_link_status(adapter); - adapter->dev_state = BE_DEV_STATE_INIT; - return 0; - -cleanup: - be_remove(pdev); - return status; -error_adapter: - pci_release_regions(pdev); -error_pci_req: - pci_disable_device(pdev); -error: - printk(KERN_ERR "BladeEngine initalization failed\n"); - return status; -} - -/* - * Get the current link status and print the status on console - */ -void be_update_link_status(struct be_adapter *adapter) -{ - int status; - struct be_net_object *pnob = adapter->net_obj; - - status = be_rxf_link_status(&pnob->fn_obj, adapter->be_link_sts, NULL, - NULL, NULL); - if (status == BE_SUCCESS) { - if (adapter->be_link_sts->mac0_speed && - adapter->be_link_sts->mac0_duplex) - adapter->port0_link_sts = BE_PORT_LINK_UP; - else - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - - if (adapter->be_link_sts->mac1_speed && - adapter->be_link_sts->mac1_duplex) - adapter->port1_link_sts = BE_PORT_LINK_UP; - else - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - - dev_info(&pnob->netdev->dev, "Link Properties:\n"); - be_print_link_info(adapter->be_link_sts); - return; - } - dev_info(&pnob->netdev->dev, "Could not get link status\n"); - return; -} - - -#ifdef CONFIG_PM -static void -be_pm_cleanup(struct be_adapter *adapter, - struct be_net_object *pnob, struct net_device *netdev) -{ - netif_carrier_off(netdev); - netif_stop_queue(netdev); - - be_wait_nic_tx_cmplx_cmpl(pnob); - be_disable_eq_intr(pnob); - - if (adapter->tasklet_started) { - tasklet_kill(&adapter->sts_handler); - adapter->tasklet_started = 0; - } - - be_unregister_isr(adapter); - be_disable_intr(pnob); - - be_tx_q_clean(pnob); - be_rx_q_clean(pnob); - - be_destroy_netobj(pnob); -} - -static int be_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct be_adapter *adapter = pci_get_drvdata(pdev); - struct net_device *netdev = adapter->netdevp; - struct be_net_object *pnob = netdev_priv(netdev); - - adapter->dev_pm_state = adapter->dev_state; - adapter->dev_state = BE_DEV_STATE_SUSPEND; - - netif_device_detach(netdev); - if (netif_running(netdev)) - be_pm_cleanup(adapter, pnob, netdev); - - pci_enable_wake(pdev, 3, 1); - pci_enable_wake(pdev, 4, 1); /* D3 Cold = 4 */ - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; -} - -static void be_up(struct be_adapter *adapter) -{ - struct be_net_object *pnob = adapter->net_obj; - - if (pnob->num_vlans != 0) - be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans, - pnob->vlan_tag, NULL, NULL, NULL); - -} - -static int be_resume(struct pci_dev *pdev) -{ - int status = 0; - struct be_adapter *adapter = pci_get_drvdata(pdev); - struct net_device *netdev = adapter->netdevp; - struct be_net_object *pnob = netdev_priv(netdev); - - netif_device_detach(netdev); - - status = pci_enable_device(pdev); - if (status) - return status; - - pci_set_power_state(pdev, 0); - pci_restore_state(pdev); - pci_enable_wake(pdev, 3, 0); - pci_enable_wake(pdev, 4, 0); /* 4 is D3 cold */ - - netif_carrier_on(netdev); - netif_start_queue(netdev); - - if (netif_running(netdev)) { - be_rxf_mac_address_read_write(&pnob->fn_obj, false, false, - false, true, false, netdev->dev_addr, NULL, NULL); - - status = be_nob_ring_init(adapter, pnob); - if (status < 0) - return status; - - tasklet_init(&(adapter->sts_handler), be_process_intr, - (unsigned long)adapter); - adapter->tasklet_started = 1; - - if (be_register_isr(adapter, pnob) != 0) { - printk(KERN_ERR "be_register_isr failed\n"); - return status; - } - - - status = be_mcc_init(adapter); - if (status < 0) { - printk(KERN_ERR "be_mcc_init failed\n"); - return status; - } - be_update_link_status(adapter); - /* - * Register async call back function to handle link - * status updates - */ - status = be_mcc_add_async_event_callback( - &adapter->net_obj->mcc_q_obj, - be_link_status_async_callback, (void *)adapter); - if (status != BE_SUCCESS) { - printk(KERN_WARNING "add_async_event_callback failed"); - printk(KERN_WARNING - "Link status changes may not be reflected\n"); - } - be_enable_intr(pnob); - be_enable_eq_intr(pnob); - be_up(adapter); - } - netif_device_attach(netdev); - adapter->dev_state = adapter->dev_pm_state; - return 0; - -} - -#endif - -/* Wait until no more pending transmits */ -void be_wait_nic_tx_cmplx_cmpl(struct be_net_object *pnob) -{ - int i; - - /* Wait for 20us * 50000 (= 1s) and no more */ - i = 0; - while ((pnob->tx_q_tl != pnob->tx_q_hd) && (i < 50000)) { - ++i; - udelay(20); - } - - /* Check for no more pending transmits */ - if (i >= 50000) { - printk(KERN_WARNING - "Did not receive completions for all TX requests\n"); - } -} - -static struct pci_driver be_driver = { - .name = be_driver_name, - .id_table = be_device_id_table, - .probe = be_probe, -#ifdef CONFIG_PM - .suspend = be_suspend, - .resume = be_resume, -#endif - .remove = be_remove -}; - -/* - * Module init entry point. Registers our our device and return. - * Our probe will be called if the device is found. - */ -static int __init be_init_module(void) -{ - int ret; - - if (rxbuf_size != 8192 && rxbuf_size != 4096 && rxbuf_size != 2048) { - printk(KERN_WARNING - "Unsupported receive buffer size (%d) requested\n", - rxbuf_size); - printk(KERN_WARNING - "Must be 2048, 4096 or 8192. Defaulting to 2048\n"); - rxbuf_size = 2048; - } - - ret = pci_register_driver(&be_driver); - - return ret; -} - -module_init(be_init_module); - -/* - * be_exit_module - Driver Exit Cleanup Routine - */ -static void __exit be_exit_module(void) -{ - pci_unregister_driver(&be_driver); -} - -module_exit(be_exit_module); diff --git a/drivers/staging/benet/be_int.c b/drivers/staging/benet/be_int.c deleted file mode 100644 index cba95d09a8b6..000000000000 --- a/drivers/staging/benet/be_int.c +++ /dev/null @@ -1,863 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include -#include - -#include "benet.h" - -/* number of bytes of RX frame that are copied to skb->data */ -#define BE_HDR_LEN 64 - -#define NETIF_RX(skb) netif_receive_skb(skb) -#define VLAN_ACCEL_RX(skb, pnob, vt) \ - vlan_hwaccel_rx(skb, pnob->vlan_grp, vt) - -/* - This function notifies BladeEngine of the number of completion - entries processed from the specified completion queue by writing - the number of popped entries to the door bell. - - pnob - Pointer to the NetObject structure - n - Number of completion entries processed - cq_id - Queue ID of the completion queue for which notification - is being done. - re_arm - 1 - rearm the completion ring to generate an event. - - 0 - dont rearm the completion ring to generate an event -*/ -void be_notify_cmpl(struct be_net_object *pnob, int n, int cq_id, int re_arm) -{ - struct CQ_DB_AMAP cqdb; - - cqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, cq_id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, re_arm); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, n); - PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]); -} - -/* - * adds additional receive frags indicated by BE starting from given - * frag index (fi) to specified skb's frag list - */ -static void -add_skb_frags(struct be_net_object *pnob, struct sk_buff *skb, - u32 nresid, u32 fi) -{ - struct be_adapter *adapter = pnob->adapter; - u32 sk_frag_idx, n; - struct be_rx_page_info *rx_page_info; - u32 frag_sz = pnob->rx_buf_size; - - sk_frag_idx = skb_shinfo(skb)->nr_frags; - while (nresid) { - index_inc(&fi, pnob->rx_q_len); - - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - pnob->rx_ctxt[fi] = NULL; - if ((rx_page_info->page_offset) || - (pnob->rx_pg_shared == false)) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - n = min(nresid, frag_sz); - skb_shinfo(skb)->frags[sk_frag_idx].page = rx_page_info->page; - skb_shinfo(skb)->frags[sk_frag_idx].page_offset - = rx_page_info->page_offset; - skb_shinfo(skb)->frags[sk_frag_idx].size = n; - - sk_frag_idx++; - skb->len += n; - skb->data_len += n; - skb_shinfo(skb)->nr_frags++; - nresid -= n; - - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - atomic_dec(&pnob->rx_q_posted); - } -} - -/* - * This function processes incoming nic packets over various Rx queues. - * This function takes the adapter, the current Rx status descriptor - * entry and the Rx completion queue ID as argument. - */ -static inline int process_nic_rx_completion(struct be_net_object *pnob, - struct ETH_RX_COMPL_AMAP *rxcp) -{ - struct be_adapter *adapter = pnob->adapter; - struct sk_buff *skb; - int udpcksm, tcpcksm; - int n; - u32 nresid, fi; - u32 frag_sz = pnob->rx_buf_size; - u8 *va; - struct be_rx_page_info *rx_page_info; - u32 numfrags, vtp, vtm, vlan_tag, pktsize; - - fi = AMAP_GET_BITS_PTR(ETH_RX_COMPL, fragndx, rxcp); - BUG_ON(fi >= (int)pnob->rx_q_len); - BUG_ON(fi < 0); - - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - BUG_ON(!rx_page_info->page); - pnob->rx_ctxt[fi] = NULL; - - /* - * If one page is used per fragment or if this is the second half of - * of the page, unmap the page here - */ - if ((rx_page_info->page_offset) || (pnob->rx_pg_shared == false)) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), frag_sz, - PCI_DMA_FROMDEVICE); - } - - atomic_dec(&pnob->rx_q_posted); - udpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, udpcksm, rxcp); - tcpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, tcpcksm, rxcp); - pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp); - /* - * get rid of RX flush completions first. - */ - if ((tcpcksm) && (udpcksm) && (pktsize == 32)) { - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - return 0; - } - skb = netdev_alloc_skb(pnob->netdev, BE_HDR_LEN + NET_IP_ALIGN); - if (skb == NULL) { - dev_info(&pnob->netdev->dev, "alloc_skb() failed\n"); - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - goto free_frags; - } - skb_reserve(skb, NET_IP_ALIGN); - - skb->dev = pnob->netdev; - - n = min(pktsize, frag_sz); - - va = page_address(rx_page_info->page) + rx_page_info->page_offset; - prefetch(va); - - skb->len = n; - skb->data_len = n; - if (n <= BE_HDR_LEN) { - memcpy(skb->data, va, n); - put_page(rx_page_info->page); - skb->data_len -= n; - skb->tail += n; - } else { - - /* Setup the SKB with page buffer information */ - skb_shinfo(skb)->frags[0].page = rx_page_info->page; - skb_shinfo(skb)->nr_frags++; - - /* Copy the header into the skb_data */ - memcpy(skb->data, va, BE_HDR_LEN); - skb_shinfo(skb)->frags[0].page_offset = - rx_page_info->page_offset + BE_HDR_LEN; - skb_shinfo(skb)->frags[0].size = n - BE_HDR_LEN; - skb->data_len -= BE_HDR_LEN; - skb->tail += BE_HDR_LEN; - } - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - nresid = pktsize - n; - - skb->protocol = eth_type_trans(skb, pnob->netdev); - - if ((tcpcksm || udpcksm) && adapter->rx_csum) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - /* - * if we have more bytes left, the frame has been - * given to us in multiple fragments. This happens - * with Jumbo frames. Add the remaining fragments to - * skb->frags[] array. - */ - if (nresid) - add_skb_frags(pnob, skb, nresid, fi); - - /* update the the true size of the skb. */ - skb->truesize = skb->len + sizeof(struct sk_buff); - - /* - * If a 802.3 frame or 802.2 LLC frame - * (i.e) contains length field in MAC Hdr - * and frame len is greater than 64 bytes - */ - if (((skb->protocol == ntohs(ETH_P_802_2)) || - (skb->protocol == ntohs(ETH_P_802_3))) - && (pktsize > BE_HDR_LEN)) { - /* - * If the length given in Mac Hdr is less than frame size - * Erraneous frame, Drop it - */ - if ((ntohs(*(u16 *) (va + 12)) + ETH_HLEN) < pktsize) { - /* Increment Non Ether type II frames dropped */ - adapter->be_stat.bes_802_3_dropped_frames++; - - kfree_skb(skb); - return 0; - } - /* - * else if the length given in Mac Hdr is greater than - * frame size, should not be seeing this sort of frames - * dump the pkt and pass to stack - */ - else if ((ntohs(*(u16 *) (va + 12)) + ETH_HLEN) > pktsize) { - /* Increment Non Ether type II frames malformed */ - adapter->be_stat.bes_802_3_malformed_frames++; - } - } - - vtp = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtp, rxcp); - vtm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtm, rxcp); - if (vtp && vtm) { - /* Vlan tag present in pkt and BE found - * that the tag matched an entry in VLAN table - */ - if (!pnob->vlan_grp || pnob->num_vlans == 0) { - /* But we have no VLANs configured. - * This should never happen. Drop the packet. - */ - dev_info(&pnob->netdev->dev, - "BladeEngine: Unexpected vlan tagged packet\n"); - kfree_skb(skb); - return 0; - } - /* pass the VLAN packet to stack */ - vlan_tag = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vlan_tag, rxcp); - VLAN_ACCEL_RX(skb, pnob, be16_to_cpu(vlan_tag)); - - } else { - NETIF_RX(skb); - } - return 0; - -free_frags: - /* free all frags associated with the current rxcp */ - numfrags = AMAP_GET_BITS_PTR(ETH_RX_COMPL, numfrags, rxcp); - while (numfrags-- > 1) { - index_inc(&fi, pnob->rx_q_len); - - rx_page_info = (struct be_rx_page_info *) - pnob->rx_ctxt[fi]; - pnob->rx_ctxt[fi] = (void *)NULL; - if (rx_page_info->page_offset || !pnob->rx_pg_shared) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - atomic_dec(&pnob->rx_q_posted); - } - return -ENOMEM; -} - -static void process_nic_rx_completion_lro(struct be_net_object *pnob, - struct ETH_RX_COMPL_AMAP *rxcp) -{ - struct be_adapter *adapter = pnob->adapter; - struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME]; - unsigned int udpcksm, tcpcksm; - u32 numfrags, vlanf, vtm, vlan_tag, nresid; - u16 vlant; - unsigned int fi, idx, n; - struct be_rx_page_info *rx_page_info; - u32 frag_sz = pnob->rx_buf_size, pktsize; - bool rx_coal = (adapter->max_rx_coal <= 1) ? 0 : 1; - u8 err, *va; - __wsum csum = 0; - - if (AMAP_GET_BITS_PTR(ETH_RX_COMPL, ipsec, rxcp)) { - /* Drop the pkt and move to the next completion. */ - adapter->be_stat.bes_rx_misc_pkts++; - return; - } - err = AMAP_GET_BITS_PTR(ETH_RX_COMPL, err, rxcp); - if (err || !rx_coal) { - /* We won't coalesce Rx pkts if the err bit set. - * take the path of normal completion processing */ - process_nic_rx_completion(pnob, rxcp); - return; - } - - fi = AMAP_GET_BITS_PTR(ETH_RX_COMPL, fragndx, rxcp); - BUG_ON(fi >= (int)pnob->rx_q_len); - BUG_ON(fi < 0); - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - BUG_ON(!rx_page_info->page); - pnob->rx_ctxt[fi] = (void *)NULL; - /* If one page is used per fragment or if this is the - * second half of the page, unmap the page here - */ - if (rx_page_info->page_offset || !pnob->rx_pg_shared) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - numfrags = AMAP_GET_BITS_PTR(ETH_RX_COMPL, numfrags, rxcp); - udpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, udpcksm, rxcp); - tcpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, tcpcksm, rxcp); - vlan_tag = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vlan_tag, rxcp); - vlant = be16_to_cpu(vlan_tag); - vlanf = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtp, rxcp); - vtm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtm, rxcp); - pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp); - - atomic_dec(&pnob->rx_q_posted); - - if (tcpcksm && udpcksm && pktsize == 32) { - /* flush completion entries */ - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - return; - } - /* Only one of udpcksum and tcpcksum can be set */ - BUG_ON(udpcksm && tcpcksm); - - /* jumbo frames could come in multiple fragments */ - BUG_ON(numfrags != ((pktsize + (frag_sz - 1)) / frag_sz)); - n = min(pktsize, frag_sz); - nresid = pktsize - n; /* will be useful for jumbo pkts */ - idx = 0; - - va = page_address(rx_page_info->page) + rx_page_info->page_offset; - prefetch(va); - rx_frags[idx].page = rx_page_info->page; - rx_frags[idx].page_offset = (rx_page_info->page_offset); - rx_frags[idx].size = n; - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - - /* If we got multiple fragments, we have more data. */ - while (nresid) { - idx++; - index_inc(&fi, pnob->rx_q_len); - - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - pnob->rx_ctxt[fi] = (void *)NULL; - if (rx_page_info->page_offset || !pnob->rx_pg_shared) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - n = min(nresid, frag_sz); - rx_frags[idx].page = rx_page_info->page; - rx_frags[idx].page_offset = (rx_page_info->page_offset); - rx_frags[idx].size = n; - - nresid -= n; - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - atomic_dec(&pnob->rx_q_posted); - } - - if (likely(!(vlanf && vtm))) { - lro_receive_frags(&pnob->lro_mgr, rx_frags, - pktsize, pktsize, - (void *)(unsigned long)csum, csum); - } else { - /* Vlan tag present in pkt and BE found - * that the tag matched an entry in VLAN table - */ - if (unlikely(!pnob->vlan_grp || pnob->num_vlans == 0)) { - /* But we have no VLANs configured. - * This should never happen. Drop the packet. - */ - dev_info(&pnob->netdev->dev, - "BladeEngine: Unexpected vlan tagged packet\n"); - return; - } - /* pass the VLAN packet to stack */ - lro_vlan_hwaccel_receive_frags(&pnob->lro_mgr, - rx_frags, pktsize, pktsize, - pnob->vlan_grp, vlant, - (void *)(unsigned long)csum, - csum); - } - - adapter->be_stat.bes_rx_coal++; -} - -struct ETH_RX_COMPL_AMAP *be_get_rx_cmpl(struct be_net_object *pnob) -{ - struct ETH_RX_COMPL_AMAP *rxcp = &pnob->rx_cq[pnob->rx_cq_tl]; - u32 valid, ct; - - valid = AMAP_GET_BITS_PTR(ETH_RX_COMPL, valid, rxcp); - if (valid == 0) - return NULL; - - ct = AMAP_GET_BITS_PTR(ETH_RX_COMPL, ct, rxcp); - if (ct != 0) { - /* Invalid chute #. treat as error */ - AMAP_SET_BITS_PTR(ETH_RX_COMPL, err, rxcp, 1); - } - - be_adv_rxcq_tl(pnob); - AMAP_SET_BITS_PTR(ETH_RX_COMPL, valid, rxcp, 0); - return rxcp; -} - -static void update_rx_rate(struct be_adapter *adapter) -{ - /* update the rate once in two seconds */ - if ((jiffies - adapter->eth_rx_jiffies) > 2 * (HZ)) { - u32 r; - r = adapter->eth_rx_bytes / - ((jiffies - adapter->eth_rx_jiffies) / (HZ)); - r = (r / 1000000); /* MB/Sec */ - - /* Mega Bits/Sec */ - adapter->be_stat.bes_eth_rx_rate = (r * 8); - adapter->eth_rx_jiffies = jiffies; - adapter->eth_rx_bytes = 0; - } -} - -static int process_rx_completions(struct be_net_object *pnob, int max_work) -{ - struct be_adapter *adapter = pnob->adapter; - struct ETH_RX_COMPL_AMAP *rxcp; - u32 nc = 0; - unsigned int pktsize; - - while (max_work && (rxcp = be_get_rx_cmpl(pnob))) { - prefetch(rxcp); - pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp); - process_nic_rx_completion_lro(pnob, rxcp); - adapter->eth_rx_bytes += pktsize; - update_rx_rate(adapter); - nc++; - max_work--; - adapter->be_stat.bes_rx_compl++; - } - if (likely(adapter->max_rx_coal > 1)) { - adapter->be_stat.bes_rx_flush++; - lro_flush_all(&pnob->lro_mgr); - } - - /* Refill the queue */ - if (atomic_read(&pnob->rx_q_posted) < 900) - be_post_eth_rx_buffs(pnob); - - return nc; -} - -static struct ETH_TX_COMPL_AMAP *be_get_tx_cmpl(struct be_net_object *pnob) -{ - struct ETH_TX_COMPL_AMAP *txcp = &pnob->tx_cq[pnob->tx_cq_tl]; - u32 valid; - - valid = AMAP_GET_BITS_PTR(ETH_TX_COMPL, valid, txcp); - if (valid == 0) - return NULL; - - AMAP_SET_BITS_PTR(ETH_TX_COMPL, valid, txcp, 0); - be_adv_txcq_tl(pnob); - return txcp; - -} - -void process_one_tx_compl(struct be_net_object *pnob, u32 end_idx) -{ - struct be_adapter *adapter = pnob->adapter; - int cur_index, tx_wrbs_completed = 0; - struct sk_buff *skb; - u64 busaddr, pa, pa_lo, pa_hi; - struct ETH_WRB_AMAP *wrb; - u32 frag_len, last_index, j; - - last_index = tx_compl_lastwrb_idx_get(pnob); - BUG_ON(last_index != end_idx); - pnob->tx_ctxt[pnob->tx_q_tl] = NULL; - do { - cur_index = pnob->tx_q_tl; - wrb = &pnob->tx_q[cur_index]; - pa_hi = AMAP_GET_BITS_PTR(ETH_WRB, frag_pa_hi, wrb); - pa_lo = AMAP_GET_BITS_PTR(ETH_WRB, frag_pa_lo, wrb); - frag_len = AMAP_GET_BITS_PTR(ETH_WRB, frag_len, wrb); - busaddr = (pa_hi << 32) | pa_lo; - if (busaddr != 0) { - pa = le64_to_cpu(busaddr); - pci_unmap_single(adapter->pdev, pa, - frag_len, PCI_DMA_TODEVICE); - } - if (cur_index == last_index) { - skb = (struct sk_buff *)pnob->tx_ctxt[cur_index]; - BUG_ON(!skb); - for (j = 0; j < skb_shinfo(skb)->nr_frags; j++) { - struct skb_frag_struct *frag; - frag = &skb_shinfo(skb)->frags[j]; - pci_unmap_page(adapter->pdev, - (ulong) frag->page, frag->size, - PCI_DMA_TODEVICE); - } - kfree_skb(skb); - pnob->tx_ctxt[cur_index] = NULL; - } else { - BUG_ON(pnob->tx_ctxt[cur_index]); - } - tx_wrbs_completed++; - be_adv_txq_tl(pnob); - } while (cur_index != last_index); - atomic_sub(tx_wrbs_completed, &pnob->tx_q_used); -} - -/* there is no need to take an SMP lock here since currently - * we have only one instance of the tasklet that does completion - * processing. - */ -static void process_nic_tx_completions(struct be_net_object *pnob) -{ - struct be_adapter *adapter = pnob->adapter; - struct ETH_TX_COMPL_AMAP *txcp; - struct net_device *netdev = pnob->netdev; - u32 end_idx, num_processed = 0; - - adapter->be_stat.bes_tx_events++; - - while ((txcp = be_get_tx_cmpl(pnob))) { - end_idx = AMAP_GET_BITS_PTR(ETH_TX_COMPL, wrb_index, txcp); - process_one_tx_compl(pnob, end_idx); - num_processed++; - adapter->be_stat.bes_tx_compl++; - } - be_notify_cmpl(pnob, num_processed, pnob->tx_cq_id, 1); - /* - * We got Tx completions and have usable WRBs. - * If the netdev's queue has been stopped - * because we had run out of WRBs, wake it now. - */ - spin_lock(&adapter->txq_lock); - if (netif_queue_stopped(netdev) - && atomic_read(&pnob->tx_q_used) < pnob->tx_q_len / 2) { - netif_wake_queue(netdev); - } - spin_unlock(&adapter->txq_lock); -} - -static u32 post_rx_buffs(struct be_net_object *pnob, struct list_head *rxbl) -{ - u32 nposted = 0; - struct ETH_RX_D_AMAP *rxd = NULL; - struct be_recv_buffer *rxbp; - void **rx_ctxp; - struct RQ_DB_AMAP rqdb; - - rx_ctxp = pnob->rx_ctxt; - - while (!list_empty(rxbl) && - (rx_ctxp[pnob->rx_q_hd] == NULL) && nposted < 255) { - - rxbp = list_first_entry(rxbl, struct be_recv_buffer, rxb_list); - list_del(&rxbp->rxb_list); - rxd = pnob->rx_q + pnob->rx_q_hd; - AMAP_SET_BITS_PTR(ETH_RX_D, fragpa_lo, rxd, rxbp->rxb_pa_lo); - AMAP_SET_BITS_PTR(ETH_RX_D, fragpa_hi, rxd, rxbp->rxb_pa_hi); - - rx_ctxp[pnob->rx_q_hd] = rxbp->rxb_ctxt; - be_adv_rxq_hd(pnob); - nposted++; - } - - if (nposted) { - /* Now press the door bell to notify BladeEngine. */ - rqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(RQ_DB, numPosted, &rqdb, nposted); - AMAP_SET_BITS_PTR(RQ_DB, rq, &rqdb, pnob->rx_q_id); - PD_WRITE(&pnob->fn_obj, erx_rq_db, rqdb.dw[0]); - } - atomic_add(nposted, &pnob->rx_q_posted); - return nposted; -} - -void be_post_eth_rx_buffs(struct be_net_object *pnob) -{ - struct be_adapter *adapter = pnob->adapter; - u32 num_bufs, r; - u64 busaddr = 0, tmp_pa; - u32 max_bufs, pg_hd; - u32 frag_size; - struct be_recv_buffer *rxbp; - struct list_head rxbl; - struct be_rx_page_info *rx_page_info; - struct page *page = NULL; - u32 page_order = 0; - gfp_t alloc_flags = GFP_ATOMIC; - - BUG_ON(!adapter); - - max_bufs = 64; /* should be even # <= 255. */ - - frag_size = pnob->rx_buf_size; - page_order = get_order(frag_size); - - if (frag_size == 8192) - alloc_flags |= (gfp_t) __GFP_COMP; - /* - * Form a linked list of RECV_BUFFFER structure to be be posted. - * We will post even number of buffer so that pages can be - * shared. - */ - INIT_LIST_HEAD(&rxbl); - - for (num_bufs = 0; num_bufs < max_bufs && - !pnob->rx_page_info[pnob->rx_pg_info_hd].page; ++num_bufs) { - - rxbp = &pnob->eth_rx_bufs[num_bufs]; - pg_hd = pnob->rx_pg_info_hd; - rx_page_info = &pnob->rx_page_info[pg_hd]; - - if (!page) { - page = alloc_pages(alloc_flags, page_order); - if (unlikely(page == NULL)) { - adapter->be_stat.bes_ethrx_post_fail++; - pnob->rxbuf_post_fail++; - break; - } - pnob->rxbuf_post_fail = 0; - busaddr = pci_map_page(adapter->pdev, page, 0, - frag_size, PCI_DMA_FROMDEVICE); - rx_page_info->page_offset = 0; - rx_page_info->page = page; - /* - * If we are sharing a page among two skbs, - * alloc a new one on the next iteration - */ - if (pnob->rx_pg_shared == false) - page = NULL; - } else { - get_page(page); - rx_page_info->page_offset += frag_size; - rx_page_info->page = page; - /* - * We are finished with the alloced page, - * Alloc a new one on the next iteration - */ - page = NULL; - } - rxbp->rxb_ctxt = (void *)rx_page_info; - index_inc(&pnob->rx_pg_info_hd, pnob->rx_q_len); - - pci_unmap_addr_set(rx_page_info, bus, busaddr); - tmp_pa = busaddr + rx_page_info->page_offset; - rxbp->rxb_pa_lo = (tmp_pa & 0xFFFFFFFF); - rxbp->rxb_pa_hi = (tmp_pa >> 32); - rxbp->rxb_len = frag_size; - list_add_tail(&rxbp->rxb_list, &rxbl); - } /* End of for */ - - r = post_rx_buffs(pnob, &rxbl); - BUG_ON(r != num_bufs); - return; -} - -/* - * Interrupt service for network function. We just schedule the - * tasklet which does all completion processing. - */ -irqreturn_t be_int(int irq, void *dev) -{ - struct net_device *netdev = dev; - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - u32 isr; - - isr = CSR_READ(&pnob->fn_obj, cev.isr1); - if (unlikely(!isr)) - return IRQ_NONE; - - spin_lock(&adapter->int_lock); - adapter->isr |= isr; - spin_unlock(&adapter->int_lock); - - adapter->be_stat.bes_ints++; - - tasklet_schedule(&adapter->sts_handler); - return IRQ_HANDLED; -} - -/* - * Poll function called by NAPI with a work budget. - * We process as many UC. BC and MC receive completions - * as the budget allows and return the actual number of - * RX ststutses processed. - */ -int be_poll(struct napi_struct *napi, int budget) -{ - struct be_net_object *pnob = - container_of(napi, struct be_net_object, napi); - u32 work_done; - - pnob->adapter->be_stat.bes_polls++; - work_done = process_rx_completions(pnob, budget); - BUG_ON(work_done > budget); - - /* All consumed */ - if (work_done < budget) { - netif_rx_complete(napi); - /* enable intr */ - be_notify_cmpl(pnob, work_done, pnob->rx_cq_id, 1); - } else { - /* More to be consumed; continue with interrupts disabled */ - be_notify_cmpl(pnob, work_done, pnob->rx_cq_id, 0); - } - return work_done; -} - -static struct EQ_ENTRY_AMAP *get_event(struct be_net_object *pnob) -{ - struct EQ_ENTRY_AMAP *eqp = &(pnob->event_q[pnob->event_q_tl]); - if (!AMAP_GET_BITS_PTR(EQ_ENTRY, Valid, eqp)) - return NULL; - be_adv_eq_tl(pnob); - return eqp; -} - -/* - * Processes all valid events in the event ring associated with given - * NetObject. Also, notifies BE the number of events processed. - */ -static inline u32 process_events(struct be_net_object *pnob) -{ - struct be_adapter *adapter = pnob->adapter; - struct EQ_ENTRY_AMAP *eqp; - u32 rid, num_events = 0; - struct net_device *netdev = pnob->netdev; - - while ((eqp = get_event(pnob)) != NULL) { - adapter->be_stat.bes_events++; - rid = AMAP_GET_BITS_PTR(EQ_ENTRY, ResourceID, eqp); - if (rid == pnob->rx_cq_id) { - adapter->be_stat.bes_rx_events++; - netif_rx_schedule(&pnob->napi); - } else if (rid == pnob->tx_cq_id) { - process_nic_tx_completions(pnob); - } else if (rid == pnob->mcc_cq_id) { - be_mcc_process_cq(&pnob->mcc_q_obj, 1); - } else { - dev_info(&netdev->dev, - "Invalid EQ ResourceID %d\n", rid); - } - AMAP_SET_BITS_PTR(EQ_ENTRY, Valid, eqp, 0); - AMAP_SET_BITS_PTR(EQ_ENTRY, ResourceID, eqp, 0); - num_events++; - } - return num_events; -} - -static void update_eqd(struct be_adapter *adapter, struct be_net_object *pnob) -{ - int status; - struct be_eq_object *eq_objectp; - - /* update once a second */ - if ((jiffies - adapter->ips_jiffies) > 1 * (HZ)) { - /* One second elapsed since last update */ - u32 r, new_eqd = -1; - r = adapter->be_stat.bes_ints - adapter->be_stat.bes_prev_ints; - r = r / ((jiffies - adapter->ips_jiffies) / (HZ)); - adapter->be_stat.bes_ips = r; - adapter->ips_jiffies = jiffies; - adapter->be_stat.bes_prev_ints = adapter->be_stat.bes_ints; - if (r > IPS_HI_WM && adapter->cur_eqd < adapter->max_eqd) - new_eqd = (adapter->cur_eqd + 8); - if (r < IPS_LO_WM && adapter->cur_eqd > adapter->min_eqd) - new_eqd = (adapter->cur_eqd - 8); - if (adapter->enable_aic && new_eqd != -1) { - eq_objectp = &pnob->event_q_obj; - status = be_eq_modify_delay(&pnob->fn_obj, 1, - &eq_objectp, &new_eqd, NULL, - NULL, NULL); - if (status == BE_SUCCESS) - adapter->cur_eqd = new_eqd; - } - } -} - -/* - This function notifies BladeEngine of how many events were processed - from the event queue by ringing the corresponding door bell and - optionally re-arms the event queue. - n - number of events processed - re_arm - 1 - re-arm the EQ, 0 - do not re-arm the EQ - -*/ -static void be_notify_event(struct be_net_object *pnob, int n, int re_arm) -{ - struct CQ_DB_AMAP eqdb; - eqdb.dw[0] = 0; - - AMAP_SET_BITS_PTR(CQ_DB, qid, &eqdb, pnob->event_q_id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &eqdb, re_arm); - AMAP_SET_BITS_PTR(CQ_DB, event, &eqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &eqdb, n); - /* - * Under some situations we see an interrupt and no valid - * EQ entry. To keep going, we need to ring the DB even if - * numPOsted is 0. - */ - PD_WRITE(&pnob->fn_obj, cq_db, eqdb.dw[0]); - return; -} - -/* - * Called from the tasklet scheduled by ISR. All real interrupt processing - * is done here. - */ -void be_process_intr(unsigned long context) -{ - struct be_adapter *adapter = (struct be_adapter *)context; - struct be_net_object *pnob = adapter->net_obj; - u32 isr, n; - ulong flags = 0; - - isr = adapter->isr; - - /* - * we create only one NIC event queue in Linux. Event is - * expected only in the first event queue - */ - BUG_ON(isr & 0xfffffffe); - if ((isr & 1) == 0) - return; /* not our interrupt */ - n = process_events(pnob); - /* - * Clear the event bit. adapter->isr is set by - * hard interrupt. Prevent race with lock. - */ - spin_lock_irqsave(&adapter->int_lock, flags); - adapter->isr &= ~1; - spin_unlock_irqrestore(&adapter->int_lock, flags); - be_notify_event(pnob, n, 1); - /* - * If previous allocation attempts had failed and - * BE has used up all posted buffers, post RX buffers here - */ - if (pnob->rxbuf_post_fail && atomic_read(&pnob->rx_q_posted) == 0) - be_post_eth_rx_buffs(pnob); - update_eqd(adapter, pnob); - return; -} diff --git a/drivers/staging/benet/be_netif.c b/drivers/staging/benet/be_netif.c deleted file mode 100644 index 2b8daf63dc7d..000000000000 --- a/drivers/staging/benet/be_netif.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * be_netif.c - * - * This file contains various entry points of drivers seen by tcp/ip stack. - */ - -#include -#include -#include "benet.h" -#include -#include - -/* Strings to print Link properties */ -static const char *link_speed[] = { - "Invalid link Speed Value", - "10 Mbps", - "100 Mbps", - "1 Gbps", - "10 Gbps" -}; - -static const char *link_duplex[] = { - "Invalid Duplex Value", - "Half Duplex", - "Full Duplex" -}; - -static const char *link_state[] = { - "", - "(active)" -}; - -void be_print_link_info(struct BE_LINK_STATUS *lnk_status) -{ - u16 si, di, ai; - - /* Port 0 */ - if (lnk_status->mac0_speed && lnk_status->mac0_duplex) { - /* Port is up and running */ - si = (lnk_status->mac0_speed < 5) ? lnk_status->mac0_speed : 0; - di = (lnk_status->mac0_duplex < 3) ? - lnk_status->mac0_duplex : 0; - ai = (lnk_status->active_port == 0) ? 1 : 0; - printk(KERN_INFO "PortNo. 0: Speed - %s %s %s\n", - link_speed[si], link_duplex[di], link_state[ai]); - } else - printk(KERN_INFO "PortNo. 0: Down\n"); - - /* Port 1 */ - if (lnk_status->mac1_speed && lnk_status->mac1_duplex) { - /* Port is up and running */ - si = (lnk_status->mac1_speed < 5) ? lnk_status->mac1_speed : 0; - di = (lnk_status->mac1_duplex < 3) ? - lnk_status->mac1_duplex : 0; - ai = (lnk_status->active_port == 0) ? 1 : 0; - printk(KERN_INFO "PortNo. 1: Speed - %s %s %s\n", - link_speed[si], link_duplex[di], link_state[ai]); - } else - printk(KERN_INFO "PortNo. 1: Down\n"); - - return; -} - -static int -be_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr, - void **ip_hdr, void **tcpudp_hdr, - u64 *hdr_flags, void *priv) -{ - struct ethhdr *eh; - struct vlan_ethhdr *veh; - struct iphdr *iph; - u8 *va = page_address(frag->page) + frag->page_offset; - unsigned long ll_hlen; - - /* find the mac header, abort if not IPv4 */ - - prefetch(va); - eh = (struct ethhdr *)va; - *mac_hdr = eh; - ll_hlen = ETH_HLEN; - if (eh->h_proto != htons(ETH_P_IP)) { - if (eh->h_proto == htons(ETH_P_8021Q)) { - veh = (struct vlan_ethhdr *)va; - if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP)) - return -1; - - ll_hlen += VLAN_HLEN; - - } else { - return -1; - } - } - *hdr_flags = LRO_IPV4; - - iph = (struct iphdr *)(va + ll_hlen); - *ip_hdr = iph; - if (iph->protocol != IPPROTO_TCP) - return -1; - *hdr_flags |= LRO_TCP; - *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2); - - return 0; -} - -static int benet_open(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - struct net_lro_mgr *lro_mgr; - - if (adapter->dev_state < BE_DEV_STATE_INIT) - return -EAGAIN; - - lro_mgr = &pnob->lro_mgr; - lro_mgr->dev = netdev; - - lro_mgr->features = LRO_F_NAPI; - lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; - lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; - lro_mgr->max_desc = BE_MAX_LRO_DESCRIPTORS; - lro_mgr->lro_arr = pnob->lro_desc; - lro_mgr->get_frag_header = be_get_frag_header; - lro_mgr->max_aggr = adapter->max_rx_coal; - lro_mgr->frag_align_pad = 2; - if (lro_mgr->max_aggr > MAX_SKB_FRAGS) - lro_mgr->max_aggr = MAX_SKB_FRAGS; - - adapter->max_rx_coal = BE_LRO_MAX_PKTS; - - be_update_link_status(adapter); - - /* - * Set carrier on only if Physical Link up - * Either of the port link status up signifies this - */ - if ((adapter->port0_link_sts == BE_PORT_LINK_UP) || - (adapter->port1_link_sts == BE_PORT_LINK_UP)) { - netif_start_queue(netdev); - netif_carrier_on(netdev); - } - - adapter->dev_state = BE_DEV_STATE_OPEN; - napi_enable(&pnob->napi); - be_enable_intr(pnob); - be_enable_eq_intr(pnob); - /* - * RX completion queue may be in dis-armed state. Arm it. - */ - be_notify_cmpl(pnob, 0, pnob->rx_cq_id, 1); - - return 0; -} - -static int benet_close(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - netif_stop_queue(netdev); - synchronize_irq(netdev->irq); - - be_wait_nic_tx_cmplx_cmpl(pnob); - adapter->dev_state = BE_DEV_STATE_INIT; - netif_carrier_off(netdev); - - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - be_disable_intr(pnob); - be_disable_eq_intr(pnob); - napi_disable(&pnob->napi); - - return 0; -} - -/* - * Setting a Mac Address for BE - * Takes netdev and a void pointer as arguments. - * The pointer holds the new addres to be used. - */ -static int benet_set_mac_addr(struct net_device *netdev, void *p) -{ - struct sockaddr *addr = p; - struct be_net_object *pnob = netdev_priv(netdev); - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - be_rxf_mac_address_read_write(&pnob->fn_obj, 0, 0, false, true, false, - netdev->dev_addr, NULL, NULL); - /* - * Since we are doing Active-Passive failover, both - * ports should have matching MAC addresses everytime. - */ - be_rxf_mac_address_read_write(&pnob->fn_obj, 1, 0, false, true, false, - netdev->dev_addr, NULL, NULL); - - return 0; -} - -void be_get_stats_timer_handler(unsigned long context) -{ - struct be_timer_ctxt *ctxt = (struct be_timer_ctxt *)context; - - if (atomic_read(&ctxt->get_stat_flag)) { - atomic_dec(&ctxt->get_stat_flag); - up((void *)ctxt->get_stat_sem_addr); - } - del_timer(&ctxt->get_stats_timer); - return; -} - -void be_get_stat_cb(void *context, int status, - struct MCC_WRB_AMAP *optional_wrb) -{ - struct be_timer_ctxt *ctxt = (struct be_timer_ctxt *)context; - /* - * just up the semaphore if the get_stat_flag - * reads 1. so that the waiter can continue. - * If it is 0, then it was handled by the timer handler. - */ - del_timer(&ctxt->get_stats_timer); - if (atomic_read(&ctxt->get_stat_flag)) { - atomic_dec(&ctxt->get_stat_flag); - up((void *)ctxt->get_stat_sem_addr); - } -} - -struct net_device_stats *benet_get_stats(struct net_device *dev) -{ - struct be_net_object *pnob = netdev_priv(dev); - struct be_adapter *adapter = pnob->adapter; - u64 pa; - struct be_timer_ctxt *ctxt = &adapter->timer_ctxt; - - if (adapter->dev_state != BE_DEV_STATE_OPEN) { - /* Return previously read stats */ - return &(adapter->benet_stats); - } - /* Get Physical Addr */ - pa = pci_map_single(adapter->pdev, adapter->eth_statsp, - sizeof(struct FWCMD_ETH_GET_STATISTICS), - PCI_DMA_FROMDEVICE); - ctxt->get_stat_sem_addr = (unsigned long)&adapter->get_eth_stat_sem; - atomic_inc(&ctxt->get_stat_flag); - - be_rxf_query_eth_statistics(&pnob->fn_obj, adapter->eth_statsp, - cpu_to_le64(pa), be_get_stat_cb, ctxt, - NULL); - - ctxt->get_stats_timer.data = (unsigned long)ctxt; - mod_timer(&ctxt->get_stats_timer, (jiffies + (HZ * 2))); - down((void *)ctxt->get_stat_sem_addr); /* callback will unblock us */ - - /* Adding port0 and port1 stats. */ - adapter->benet_stats.rx_packets = - adapter->eth_statsp->params.response.p0recvdtotalframes + - adapter->eth_statsp->params.response.p1recvdtotalframes; - adapter->benet_stats.tx_packets = - adapter->eth_statsp->params.response.p0xmitunicastframes + - adapter->eth_statsp->params.response.p1xmitunicastframes; - adapter->benet_stats.tx_bytes = - adapter->eth_statsp->params.response.p0xmitbyteslsd + - adapter->eth_statsp->params.response.p1xmitbyteslsd; - adapter->benet_stats.rx_errors = - adapter->eth_statsp->params.response.p0crcerrors + - adapter->eth_statsp->params.response.p1crcerrors; - adapter->benet_stats.rx_errors += - adapter->eth_statsp->params.response.p0alignmentsymerrs + - adapter->eth_statsp->params.response.p1alignmentsymerrs; - adapter->benet_stats.rx_errors += - adapter->eth_statsp->params.response.p0inrangelenerrors + - adapter->eth_statsp->params.response.p1inrangelenerrors; - adapter->benet_stats.rx_bytes = - adapter->eth_statsp->params.response.p0recvdtotalbytesLSD + - adapter->eth_statsp->params.response.p1recvdtotalbytesLSD; - adapter->benet_stats.rx_crc_errors = - adapter->eth_statsp->params.response.p0crcerrors + - adapter->eth_statsp->params.response.p1crcerrors; - - adapter->benet_stats.tx_packets += - adapter->eth_statsp->params.response.p0xmitmulticastframes + - adapter->eth_statsp->params.response.p1xmitmulticastframes; - adapter->benet_stats.tx_packets += - adapter->eth_statsp->params.response.p0xmitbroadcastframes + - adapter->eth_statsp->params.response.p1xmitbroadcastframes; - adapter->benet_stats.tx_errors = 0; - - adapter->benet_stats.multicast = - adapter->eth_statsp->params.response.p0xmitmulticastframes + - adapter->eth_statsp->params.response.p1xmitmulticastframes; - - adapter->benet_stats.rx_fifo_errors = - adapter->eth_statsp->params.response.p0rxfifooverflowdropped + - adapter->eth_statsp->params.response.p1rxfifooverflowdropped; - adapter->benet_stats.rx_frame_errors = - adapter->eth_statsp->params.response.p0alignmentsymerrs + - adapter->eth_statsp->params.response.p1alignmentsymerrs; - adapter->benet_stats.rx_length_errors = - adapter->eth_statsp->params.response.p0inrangelenerrors + - adapter->eth_statsp->params.response.p1inrangelenerrors; - adapter->benet_stats.rx_length_errors += - adapter->eth_statsp->params.response.p0outrangeerrors + - adapter->eth_statsp->params.response.p1outrangeerrors; - adapter->benet_stats.rx_length_errors += - adapter->eth_statsp->params.response.p0frametoolongerrors + - adapter->eth_statsp->params.response.p1frametoolongerrors; - - pci_unmap_single(adapter->pdev, (ulong) adapter->eth_statsp, - sizeof(struct FWCMD_ETH_GET_STATISTICS), - PCI_DMA_FROMDEVICE); - return &(adapter->benet_stats); - -} - -static void be_start_tx(struct be_net_object *pnob, u32 nposted) -{ -#define CSR_ETH_MAX_SQPOSTS 255 - struct SQ_DB_AMAP sqdb; - - sqdb.dw[0] = 0; - - AMAP_SET_BITS_PTR(SQ_DB, cid, &sqdb, pnob->tx_q_id); - while (nposted) { - if (nposted > CSR_ETH_MAX_SQPOSTS) { - AMAP_SET_BITS_PTR(SQ_DB, numPosted, &sqdb, - CSR_ETH_MAX_SQPOSTS); - nposted -= CSR_ETH_MAX_SQPOSTS; - } else { - AMAP_SET_BITS_PTR(SQ_DB, numPosted, &sqdb, nposted); - nposted = 0; - } - PD_WRITE(&pnob->fn_obj, etx_sq_db, sqdb.dw[0]); - } - - return; -} - -static void update_tx_rate(struct be_adapter *adapter) -{ - /* update the rate once in two seconds */ - if ((jiffies - adapter->eth_tx_jiffies) > 2 * (HZ)) { - u32 r; - r = adapter->eth_tx_bytes / - ((jiffies - adapter->eth_tx_jiffies) / (HZ)); - r = (r / 1000000); /* M bytes/s */ - adapter->be_stat.bes_eth_tx_rate = (r * 8); /* M bits/s */ - adapter->eth_tx_jiffies = jiffies; - adapter->eth_tx_bytes = 0; - } -} - -static int wrb_cnt_in_skb(struct sk_buff *skb) -{ - int cnt = 0; - while (skb) { - if (skb->len > skb->data_len) - cnt++; - cnt += skb_shinfo(skb)->nr_frags; - skb = skb_shinfo(skb)->frag_list; - } - BUG_ON(cnt > BE_MAX_TX_FRAG_COUNT); - return cnt; -} - -static void wrb_fill(struct ETH_WRB_AMAP *wrb, u64 addr, int len) -{ - AMAP_SET_BITS_PTR(ETH_WRB, frag_pa_hi, wrb, addr >> 32); - AMAP_SET_BITS_PTR(ETH_WRB, frag_pa_lo, wrb, addr & 0xFFFFFFFF); - AMAP_SET_BITS_PTR(ETH_WRB, frag_len, wrb, len); -} - -static void wrb_fill_extra(struct ETH_WRB_AMAP *wrb, struct sk_buff *skb, - struct be_net_object *pnob) -{ - wrb->dw[2] = 0; - wrb->dw[3] = 0; - AMAP_SET_BITS_PTR(ETH_WRB, crc, wrb, 1); - if (skb_shinfo(skb)->gso_segs > 1 && skb_shinfo(skb)->gso_size) { - AMAP_SET_BITS_PTR(ETH_WRB, lso, wrb, 1); - AMAP_SET_BITS_PTR(ETH_WRB, lso_mss, wrb, - skb_shinfo(skb)->gso_size); - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - u8 proto = ((struct iphdr *)ip_hdr(skb))->protocol; - if (proto == IPPROTO_TCP) - AMAP_SET_BITS_PTR(ETH_WRB, tcpcs, wrb, 1); - else if (proto == IPPROTO_UDP) - AMAP_SET_BITS_PTR(ETH_WRB, udpcs, wrb, 1); - } - if (pnob->vlan_grp && vlan_tx_tag_present(skb)) { - AMAP_SET_BITS_PTR(ETH_WRB, vlan, wrb, 1); - AMAP_SET_BITS_PTR(ETH_WRB, vlan_tag, wrb, vlan_tx_tag_get(skb)); - } -} - -static inline void wrb_copy_extra(struct ETH_WRB_AMAP *to, - struct ETH_WRB_AMAP *from) -{ - - to->dw[2] = from->dw[2]; - to->dw[3] = from->dw[3]; -} - -/* Returns the actual count of wrbs used including a possible dummy */ -static int copy_skb_to_txq(struct be_net_object *pnob, struct sk_buff *skb, - u32 wrb_cnt, u32 *copied) -{ - u64 busaddr; - struct ETH_WRB_AMAP *wrb = NULL, *first = NULL; - u32 i; - bool dummy = true; - struct pci_dev *pdev = pnob->adapter->pdev; - - if (wrb_cnt & 1) - wrb_cnt++; - else - dummy = false; - - atomic_add(wrb_cnt, &pnob->tx_q_used); - - while (skb) { - if (skb->len > skb->data_len) { - int len = skb->len - skb->data_len; - busaddr = pci_map_single(pdev, skb->data, len, - PCI_DMA_TODEVICE); - busaddr = cpu_to_le64(busaddr); - wrb = &pnob->tx_q[pnob->tx_q_hd]; - if (first == NULL) { - wrb_fill_extra(wrb, skb, pnob); - first = wrb; - } else { - wrb_copy_extra(wrb, first); - } - wrb_fill(wrb, busaddr, len); - be_adv_txq_hd(pnob); - *copied += len; - } - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - struct skb_frag_struct *frag = - &skb_shinfo(skb)->frags[i]; - busaddr = pci_map_page(pdev, frag->page, - frag->page_offset, frag->size, - PCI_DMA_TODEVICE); - busaddr = cpu_to_le64(busaddr); - wrb = &pnob->tx_q[pnob->tx_q_hd]; - if (first == NULL) { - wrb_fill_extra(wrb, skb, pnob); - first = wrb; - } else { - wrb_copy_extra(wrb, first); - } - wrb_fill(wrb, busaddr, frag->size); - be_adv_txq_hd(pnob); - *copied += frag->size; - } - skb = skb_shinfo(skb)->frag_list; - } - - if (dummy) { - wrb = &pnob->tx_q[pnob->tx_q_hd]; - BUG_ON(first == NULL); - wrb_copy_extra(wrb, first); - wrb_fill(wrb, 0, 0); - be_adv_txq_hd(pnob); - } - AMAP_SET_BITS_PTR(ETH_WRB, complete, wrb, 1); - AMAP_SET_BITS_PTR(ETH_WRB, last, wrb, 1); - return wrb_cnt; -} - -/* For each skb transmitted, tx_ctxt stores the num of wrbs in the - * start index and skb pointer in the end index - */ -static inline void be_tx_wrb_info_remember(struct be_net_object *pnob, - struct sk_buff *skb, int wrb_cnt, - u32 start) -{ - *(u32 *) (&pnob->tx_ctxt[start]) = wrb_cnt; - index_adv(&start, wrb_cnt - 1, pnob->tx_q_len); - pnob->tx_ctxt[start] = skb; -} - -static int benet_xmit(struct sk_buff *skb, struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - u32 wrb_cnt, copied = 0; - u32 start = pnob->tx_q_hd; - - adapter->be_stat.bes_tx_reqs++; - - wrb_cnt = wrb_cnt_in_skb(skb); - spin_lock_bh(&adapter->txq_lock); - if ((pnob->tx_q_len - 2 - atomic_read(&pnob->tx_q_used)) <= wrb_cnt) { - netif_stop_queue(pnob->netdev); - spin_unlock_bh(&adapter->txq_lock); - adapter->be_stat.bes_tx_fails++; - return NETDEV_TX_BUSY; - } - spin_unlock_bh(&adapter->txq_lock); - - wrb_cnt = copy_skb_to_txq(pnob, skb, wrb_cnt, &copied); - be_tx_wrb_info_remember(pnob, skb, wrb_cnt, start); - - be_start_tx(pnob, wrb_cnt); - - adapter->eth_tx_bytes += copied; - adapter->be_stat.bes_tx_wrbs += wrb_cnt; - update_tx_rate(adapter); - netdev->trans_start = jiffies; - - return NETDEV_TX_OK; -} - -/* - * This is the driver entry point to change the mtu of the device - * Returns 0 for success and errno for failure. - */ -static int benet_change_mtu(struct net_device *netdev, int new_mtu) -{ - /* - * BE supports jumbo frame size upto 9000 bytes including the link layer - * header. Considering the different variants of frame formats possible - * like VLAN, SNAP/LLC, the maximum possible value for MTU is 8974 bytes - */ - - if (new_mtu < (ETH_ZLEN + ETH_FCS_LEN) || (new_mtu > BE_MAX_MTU)) { - dev_info(&netdev->dev, "Invalid MTU requested. " - "Must be between %d and %d bytes\n", - (ETH_ZLEN + ETH_FCS_LEN), BE_MAX_MTU); - return -EINVAL; - } - dev_info(&netdev->dev, "MTU changed from %d to %d\n", - netdev->mtu, new_mtu); - netdev->mtu = new_mtu; - return 0; -} - -/* - * This is the driver entry point to register a vlan with the device - */ -static void benet_vlan_register(struct net_device *netdev, - struct vlan_group *grp) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - be_disable_eq_intr(pnob); - pnob->vlan_grp = grp; - pnob->num_vlans = 0; - be_enable_eq_intr(pnob); -} - -/* - * This is the driver entry point to add a vlan vlan_id - * with the device netdev - */ -static void benet_vlan_add_vid(struct net_device *netdev, u16 vlan_id) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - if (pnob->num_vlans == (BE_NUM_VLAN_SUPPORTED - 1)) { - /* no way to return an error */ - dev_info(&netdev->dev, - "BladeEngine: Cannot configure more than %d Vlans\n", - BE_NUM_VLAN_SUPPORTED); - return; - } - /* The new vlan tag will be in the slot indicated by num_vlans. */ - pnob->vlan_tag[pnob->num_vlans++] = vlan_id; - be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans, - pnob->vlan_tag, NULL, NULL, NULL); -} - -/* - * This is the driver entry point to remove a vlan vlan_id - * with the device netdev - */ -static void benet_vlan_rem_vid(struct net_device *netdev, u16 vlan_id) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - u32 i, value; - - /* - * In Blade Engine, we support 32 vlan tag filters across both ports. - * To program a vlan tag, the RXF_RTPR_CSR register is used. - * Each 32-bit value of RXF_RTDR_CSR can address 2 vlan tag entries. - * The Vlan table is of depth 16. thus we support 32 tags. - */ - - value = vlan_id | VLAN_VALID_BIT; - for (i = 0; i < BE_NUM_VLAN_SUPPORTED; i++) { - if (pnob->vlan_tag[i] == vlan_id) - break; - } - - if (i == BE_NUM_VLAN_SUPPORTED) - return; - /* Now compact the vlan tag array by removing hole created. */ - while ((i + 1) < BE_NUM_VLAN_SUPPORTED) { - pnob->vlan_tag[i] = pnob->vlan_tag[i + 1]; - i++; - } - if ((i + 1) == BE_NUM_VLAN_SUPPORTED) - pnob->vlan_tag[i] = (u16) 0x0; - pnob->num_vlans--; - be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans, - pnob->vlan_tag, NULL, NULL, NULL); -} - -/* - * This function is called to program multicast - * address in the multicast filter of the ASIC. - */ -static void be_set_multicast_filter(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct dev_mc_list *mc_ptr; - u8 mac_addr[32][ETH_ALEN]; - int i; - - if (netdev->flags & IFF_ALLMULTI) { - /* set BE in Multicast promiscuous */ - be_rxf_multicast_config(&pnob->fn_obj, true, 0, NULL, NULL, - NULL, NULL); - return; - } - - for (mc_ptr = netdev->mc_list, i = 0; mc_ptr; - mc_ptr = mc_ptr->next, i++) { - memcpy(&mac_addr[i][0], mc_ptr->dmi_addr, ETH_ALEN); - } - - /* reset the promiscuous mode also. */ - be_rxf_multicast_config(&pnob->fn_obj, false, i, - &mac_addr[0][0], NULL, NULL, NULL); -} - -/* - * This is the driver entry point to set multicast list - * with the device netdev. This function will be used to - * set promiscuous mode or multicast promiscuous mode - * or multicast mode.... - */ -static void benet_set_multicast_list(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - if (netdev->flags & IFF_PROMISC) { - be_rxf_promiscuous(&pnob->fn_obj, 1, 1, NULL, NULL, NULL); - } else { - be_rxf_promiscuous(&pnob->fn_obj, 0, 0, NULL, NULL, NULL); - be_set_multicast_filter(netdev); - } -} - -int benet_init(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - ether_setup(netdev); - - netdev->open = &benet_open; - netdev->stop = &benet_close; - netdev->hard_start_xmit = &benet_xmit; - - netdev->get_stats = &benet_get_stats; - - netdev->set_multicast_list = &benet_set_multicast_list; - - netdev->change_mtu = &benet_change_mtu; - netdev->set_mac_address = &benet_set_mac_addr; - - netdev->vlan_rx_register = benet_vlan_register; - netdev->vlan_rx_add_vid = benet_vlan_add_vid; - netdev->vlan_rx_kill_vid = benet_vlan_rem_vid; - - netdev->features = - NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | - NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM; - - netdev->flags |= IFF_MULTICAST; - - /* If device is DAC Capable, set the HIGHDMA flag for netdevice. */ - if (adapter->dma_64bit_cap) - netdev->features |= NETIF_F_HIGHDMA; - - SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); - return 0; -} diff --git a/drivers/staging/benet/benet.h b/drivers/staging/benet/benet.h deleted file mode 100644 index 09a1f0817722..000000000000 --- a/drivers/staging/benet/benet.h +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#ifndef _BENET_H_ -#define _BENET_H_ - -#include -#include -#include -#include "hwlib.h" - -#define _SA_MODULE_NAME "net-driver" - -#define VLAN_VALID_BIT 0x8000 -#define BE_NUM_VLAN_SUPPORTED 32 -#define BE_PORT_LINK_DOWN 0000 -#define BE_PORT_LINK_UP 0001 -#define BE_MAX_TX_FRAG_COUNT (30) - -/* Flag bits for send operation */ -#define IPCS (1 << 0) /* Enable IP checksum offload */ -#define UDPCS (1 << 1) /* Enable UDP checksum offload */ -#define TCPCS (1 << 2) /* Enable TCP checksum offload */ -#define LSO (1 << 3) /* Enable Large Segment offload */ -#define ETHVLAN (1 << 4) /* Enable VLAN insert */ -#define ETHEVENT (1 << 5) /* Generate event on completion */ -#define ETHCOMPLETE (1 << 6) /* Generate completion when done */ -#define IPSEC (1 << 7) /* Enable IPSEC */ -#define FORWARD (1 << 8) /* Send the packet in forwarding path */ -#define FIN (1 << 9) /* Issue FIN segment */ - -#define BE_MAX_MTU 8974 - -#define BE_MAX_LRO_DESCRIPTORS 8 -#define BE_LRO_MAX_PKTS 64 -#define BE_MAX_FRAGS_PER_FRAME 6 - -extern const char be_drvr_ver[]; -extern char be_fw_ver[]; -extern char be_driver_name[]; - -extern struct ethtool_ops be_ethtool_ops; - -#define BE_DEV_STATE_NONE 0 -#define BE_DEV_STATE_INIT 1 -#define BE_DEV_STATE_OPEN 2 -#define BE_DEV_STATE_SUSPEND 3 - -/* This structure is used to describe physical fragments to use - * for DMAing data from NIC. - */ -struct be_recv_buffer { - struct list_head rxb_list; /* for maintaining a linked list */ - void *rxb_va; /* buffer virtual address */ - u32 rxb_pa_lo; /* low part of physical address */ - u32 rxb_pa_hi; /* high part of physical address */ - u32 rxb_len; /* length of recv buffer */ - void *rxb_ctxt; /* context for OSM driver to use */ -}; - -/* - * fragment list to describe scattered data. - */ -struct be_tx_frag_list { - u32 txb_len; /* Size of this fragment */ - u32 txb_pa_lo; /* Lower 32 bits of 64 bit physical addr */ - u32 txb_pa_hi; /* Higher 32 bits of 64 bit physical addr */ -}; - -struct be_rx_page_info { - struct page *page; - dma_addr_t bus; - u16 page_offset; -}; - -/* - * This structure is the main tracking structure for a NIC interface. - */ -struct be_net_object { - /* MCC Ring - used to send fwcmds to embedded ARM processor */ - struct MCC_WRB_AMAP *mcc_q; /* VA of the start of the ring */ - u32 mcc_q_len; /* # of WRB entries in this ring */ - u32 mcc_q_size; - u32 mcc_q_hd; /* MCC ring head */ - u8 mcc_q_created; /* flag to help cleanup */ - struct be_mcc_object mcc_q_obj; /* BECLIB's MCC ring Object */ - dma_addr_t mcc_q_bus; /* DMA'ble bus address */ - - /* MCC Completion Ring - FW responses to fwcmds sent from MCC ring */ - struct MCC_CQ_ENTRY_AMAP *mcc_cq; /* VA of the start of the ring */ - u32 mcc_cq_len; /* # of compl. entries in this ring */ - u32 mcc_cq_size; - u32 mcc_cq_tl; /* compl. ring tail */ - u8 mcc_cq_created; /* flag to help cleanup */ - struct be_cq_object mcc_cq_obj; /* BECLIB's MCC compl. ring object */ - u32 mcc_cq_id; /* MCC ring ID */ - dma_addr_t mcc_cq_bus; /* DMA'ble bus address */ - - struct ring_desc mb_rd; /* RD for MCC_MAIL_BOX */ - void *mb_ptr; /* mailbox ptr to be freed */ - dma_addr_t mb_bus; /* DMA'ble bus address */ - u32 mb_size; - - /* BEClib uses an array of context objects to track outstanding - * requests to the MCC. We need allocate the same number of - * conext entries as the number of entries in the MCC WRB ring - */ - u32 mcc_wrb_ctxt_size; - void *mcc_wrb_ctxt; /* pointer to the context area */ - u32 mcc_wrb_ctxtLen; /* Number of entries in the context */ - /* - * NIC send request ring - used for xmitting raw ether frames. - */ - struct ETH_WRB_AMAP *tx_q; /* VA of the start of the ring */ - u32 tx_q_len; /* # if entries in the send ring */ - u32 tx_q_size; - u32 tx_q_hd; /* Head index. Next req. goes here */ - u32 tx_q_tl; /* Tail indx. oldest outstanding req. */ - u8 tx_q_created; /* flag to help cleanup */ - struct be_ethsq_object tx_q_obj;/* BECLIB's send Q handle */ - dma_addr_t tx_q_bus; /* DMA'ble bus address */ - u32 tx_q_id; /* send queue ring ID */ - u32 tx_q_port; /* 0 no binding, 1 port A, 2 port B */ - atomic_t tx_q_used; /* # of WRBs used */ - /* ptr to an array in which we store context info for each send req. */ - void **tx_ctxt; - /* - * NIC Send compl. ring - completion status for all NIC frames xmitted. - */ - struct ETH_TX_COMPL_AMAP *tx_cq;/* VA of start of the ring */ - u32 txcq_len; /* # of entries in the ring */ - u32 tx_cq_size; - /* - * index into compl ring where the host expects next completion entry - */ - u32 tx_cq_tl; - u32 tx_cq_id; /* completion queue id */ - u8 tx_cq_created; /* flag to help cleanup */ - struct be_cq_object tx_cq_obj; - dma_addr_t tx_cq_bus; /* DMA'ble bus address */ - /* - * Event Queue - all completion entries post events here. - */ - struct EQ_ENTRY_AMAP *event_q; /* VA of start of event queue */ - u32 event_q_len; /* # of entries */ - u32 event_q_size; - u32 event_q_tl; /* Tail of the event queue */ - u32 event_q_id; /* Event queue ID */ - u8 event_q_created; /* flag to help cleanup */ - struct be_eq_object event_q_obj; /* Queue handle */ - dma_addr_t event_q_bus; /* DMA'ble bus address */ - /* - * NIC receive queue - Data buffers to be used for receiving unicast, - * broadcast and multi-cast frames are posted here. - */ - struct ETH_RX_D_AMAP *rx_q; /* VA of start of the queue */ - u32 rx_q_len; /* # of entries */ - u32 rx_q_size; - u32 rx_q_hd; /* Head of the queue */ - atomic_t rx_q_posted; /* number of posted buffers */ - u32 rx_q_id; /* queue ID */ - u8 rx_q_created; /* flag to help cleanup */ - struct be_ethrq_object rx_q_obj; /* NIC RX queue handle */ - dma_addr_t rx_q_bus; /* DMA'ble bus address */ - /* - * Pointer to an array of opaque context object for use by OSM driver - */ - void **rx_ctxt; - /* - * NIC unicast RX completion queue - all unicast ether frame completion - * statuses from BE come here. - */ - struct ETH_RX_COMPL_AMAP *rx_cq; /* VA of start of the queue */ - u32 rx_cq_len; /* # of entries */ - u32 rx_cq_size; - u32 rx_cq_tl; /* Tail of the queue */ - u32 rx_cq_id; /* queue ID */ - u8 rx_cq_created; /* flag to help cleanup */ - struct be_cq_object rx_cq_obj; /* queue handle */ - dma_addr_t rx_cq_bus; /* DMA'ble bus address */ - struct be_function_object fn_obj; /* function object */ - bool fn_obj_created; - u32 rx_buf_size; /* Size of the RX buffers */ - - struct net_device *netdev; - struct be_recv_buffer eth_rx_bufs[256]; /* to pass Rx buffer - addresses */ - struct be_adapter *adapter; /* Pointer to OSM adapter */ - u32 devno; /* OSM, network dev no. */ - u32 use_port; /* Current active port */ - struct be_rx_page_info *rx_page_info; /* Array of Rx buf pages */ - u32 rx_pg_info_hd; /* Head of queue */ - int rxbuf_post_fail; /* RxBuff posting fail count */ - bool rx_pg_shared; /* Is an allocsted page shared as two frags ? */ - struct vlan_group *vlan_grp; - u32 num_vlans; /* Number of vlans in BE's filter */ - u16 vlan_tag[BE_NUM_VLAN_SUPPORTED]; /* vlans currently configured */ - struct napi_struct napi; - struct net_lro_mgr lro_mgr; - struct net_lro_desc lro_desc[BE_MAX_LRO_DESCRIPTORS]; -}; - -#define NET_FH(np) (&(np)->fn_obj) - -/* - * BE driver statistics. - */ -struct be_drvr_stat { - u32 bes_tx_reqs; /* number of TX requests initiated */ - u32 bes_tx_fails; /* number of TX requests that failed */ - u32 bes_fwd_reqs; /* number of send reqs through forwarding i/f */ - u32 bes_tx_wrbs; /* number of tx WRBs used */ - - u32 bes_ints; /* number of interrupts */ - u32 bes_polls; /* number of times NAPI called poll function */ - u32 bes_events; /* total evet entries processed */ - u32 bes_tx_events; /* number of tx completion events */ - u32 bes_rx_events; /* number of ucast rx completion events */ - u32 bes_tx_compl; /* number of tx completion entries processed */ - u32 bes_rx_compl; /* number of rx completion entries - processed */ - u32 bes_ethrx_post_fail; /* number of ethrx buffer alloc - failures */ - /* - * number of non ether type II frames dropped where - * frame len > length field of Mac Hdr - */ - u32 bes_802_3_dropped_frames; - /* - * number of non ether type II frames malformed where - * in frame len < length field of Mac Hdr - */ - u32 bes_802_3_malformed_frames; - u32 bes_ips; /* interrupts / sec */ - u32 bes_prev_ints; /* bes_ints at last IPS calculation */ - u16 bes_eth_tx_rate; /* ETH TX rate - Mb/sec */ - u16 bes_eth_rx_rate; /* ETH RX rate - Mb/sec */ - u32 bes_rx_coal; /* Num pkts coalasced */ - u32 bes_rx_flush; /* Num times coalasced */ - u32 bes_link_change_physical; /*Num of times physical link changed */ - u32 bes_link_change_virtual; /*Num of times virtual link changed */ - u32 bes_rx_misc_pkts; /* Misc pkts received */ -}; - -/* Maximum interrupt delay (in microseconds) allowed */ -#define MAX_EQD 120 - -/* - * timer to prevent system shutdown hang for ever if h/w stops responding - */ -struct be_timer_ctxt { - atomic_t get_stat_flag; - struct timer_list get_stats_timer; - unsigned long get_stat_sem_addr; -} ; - -/* This structure is the main BladeEngine driver context. */ -struct be_adapter { - struct net_device *netdevp; - struct be_drvr_stat be_stat; - struct net_device_stats benet_stats; - - /* PCI BAR mapped addresses */ - u8 __iomem *csr_va; /* CSR */ - u8 __iomem *db_va; /* Door Bell */ - u8 __iomem *pci_va; /* PCI Config */ - - struct tasklet_struct sts_handler; - struct timer_list cq_timer; - spinlock_t int_lock; /* to protect the isr field in adapter */ - - struct FWCMD_ETH_GET_STATISTICS *eth_statsp; - /* - * This will enable the use of ethtool to enable or disable - * Checksum on Rx pkts to be obeyed or disobeyed. - * If this is true = 1, then whatever is the checksum on the - * Received pkt as per BE, it will be given to the stack. - * Else the stack will re calculate it. - */ - bool rx_csum; - /* - * This will enable the use of ethtool to enable or disable - * Coalese on Rx pkts to be obeyed or disobeyed. - * If this is grater than 0 and less than 16 then coalascing - * is enabled else it is disabled - */ - u32 max_rx_coal; - struct pci_dev *pdev; /* Pointer to OS's PCI dvice */ - - spinlock_t txq_lock; /* to stop/wake queue based on tx_q_used */ - - u32 isr; /* copy of Intr status reg. */ - - u32 port0_link_sts; /* Port 0 link status */ - u32 port1_link_sts; /* port 1 list status */ - struct BE_LINK_STATUS *be_link_sts; - - /* pointer to the first netobject of this adapter */ - struct be_net_object *net_obj; - - /* Flags to indicate what to clean up */ - bool tasklet_started; - bool isr_registered; - /* - * adaptive interrupt coalescing (AIC) related - */ - bool enable_aic; /* 1 if AIC is enabled */ - u16 min_eqd; /* minimum EQ delay in usec */ - u16 max_eqd; /* minimum EQ delay in usec */ - u16 cur_eqd; /* current EQ delay in usec */ - /* - * book keeping for interrupt / sec and TX/RX rate calculation - */ - ulong ips_jiffies; /* jiffies at last IPS calc */ - u32 eth_tx_bytes; - ulong eth_tx_jiffies; - u32 eth_rx_bytes; - ulong eth_rx_jiffies; - - struct semaphore get_eth_stat_sem; - - /* timer ctxt to prevent shutdown hanging due to un-responsive BE */ - struct be_timer_ctxt timer_ctxt; - -#define BE_MAX_MSIX_VECTORS 32 -#define BE_MAX_REQ_MSIX_VECTORS 1 /* only one EQ in Linux driver */ - struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS]; - bool msix_enabled; - bool dma_64bit_cap; /* the Device DAC capable or not */ - u8 dev_state; /* The current state of the device */ - u8 dev_pm_state; /* The State of device before going to suspend */ -}; - -/* - * Every second we look at the ints/sec and adjust eq_delay - * between adapter->min_eqd and adapter->max_eqd to keep the ints/sec between - * IPS_HI_WM and IPS_LO_WM. - */ -#define IPS_HI_WM 18000 -#define IPS_LO_WM 8000 - - -static inline void index_adv(u32 *index, u32 val, u32 limit) -{ - BUG_ON(limit & (limit-1)); - *index = (*index + val) & (limit - 1); -} - -static inline void index_inc(u32 *index, u32 limit) -{ - BUG_ON(limit & (limit-1)); - *index = (*index + 1) & (limit - 1); -} - -static inline void be_adv_eq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->event_q_tl, pnob->event_q_len); -} - -static inline void be_adv_txq_hd(struct be_net_object *pnob) -{ - index_inc(&pnob->tx_q_hd, pnob->tx_q_len); -} - -static inline void be_adv_txq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->tx_q_tl, pnob->tx_q_len); -} - -static inline void be_adv_txcq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->tx_cq_tl, pnob->txcq_len); -} - -static inline void be_adv_rxq_hd(struct be_net_object *pnob) -{ - index_inc(&pnob->rx_q_hd, pnob->rx_q_len); -} - -static inline void be_adv_rxcq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->rx_cq_tl, pnob->rx_cq_len); -} - -static inline u32 tx_compl_lastwrb_idx_get(struct be_net_object *pnob) -{ - return (pnob->tx_q_tl + *(u32 *)&pnob->tx_ctxt[pnob->tx_q_tl] - 1) - & (pnob->tx_q_len - 1); -} - -int benet_init(struct net_device *); -int be_ethtool_ioctl(struct net_device *, struct ifreq *); -struct net_device_stats *benet_get_stats(struct net_device *); -void be_process_intr(unsigned long context); -irqreturn_t be_int(int irq, void *dev); -void be_post_eth_rx_buffs(struct be_net_object *); -void be_get_stat_cb(void *, int, struct MCC_WRB_AMAP *); -void be_get_stats_timer_handler(unsigned long); -void be_wait_nic_tx_cmplx_cmpl(struct be_net_object *); -void be_print_link_info(struct BE_LINK_STATUS *); -void be_update_link_status(struct be_adapter *); -void be_init_procfs(struct be_adapter *); -void be_cleanup_procfs(struct be_adapter *); -int be_poll(struct napi_struct *, int); -struct ETH_RX_COMPL_AMAP *be_get_rx_cmpl(struct be_net_object *); -void be_notify_cmpl(struct be_net_object *, int, int, int); -void be_enable_intr(struct be_net_object *); -void be_enable_eq_intr(struct be_net_object *); -void be_disable_intr(struct be_net_object *); -void be_disable_eq_intr(struct be_net_object *); -int be_set_uc_mac_adr(struct be_net_object *, u8, u8, u8, - u8 *, mcc_wrb_cqe_callback, void *); -int be_get_flow_ctl(struct be_function_object *pFnObj, bool *, bool *); -void process_one_tx_compl(struct be_net_object *pnob, u32 end_idx); - -#endif /* _BENET_H_ */ diff --git a/drivers/staging/benet/bestatus.h b/drivers/staging/benet/bestatus.h deleted file mode 100644 index 59c7a4b62223..000000000000 --- a/drivers/staging/benet/bestatus.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#ifndef _BESTATUS_H_ -#define _BESTATUS_H_ - -#define BE_SUCCESS (0x00000000L) -/* - * MessageId: BE_PENDING - * The BladeEngine Driver call succeeded, and pended operation. - */ -#define BE_PENDING (0x20070001L) -#define BE_STATUS_PENDING (BE_PENDING) -/* - * MessageId: BE_NOT_OK - * An error occurred. - */ -#define BE_NOT_OK (0xE0070002L) -/* - * MessageId: BE_STATUS_SYSTEM_RESOURCES - * Insufficient host system resources exist to complete the API. - */ -#define BE_STATUS_SYSTEM_RESOURCES (0xE0070003L) -/* - * MessageId: BE_STATUS_CHIP_RESOURCES - * Insufficient chip resources exist to complete the API. - */ -#define BE_STATUS_CHIP_RESOURCES (0xE0070004L) -/* - * MessageId: BE_STATUS_NO_RESOURCE - * Insufficient resources to complete request. - */ -#define BE_STATUS_NO_RESOURCE (0xE0070005L) -/* - * MessageId: BE_STATUS_BUSY - * Resource is currently busy. - */ -#define BE_STATUS_BUSY (0xE0070006L) -/* - * MessageId: BE_STATUS_INVALID_PARAMETER - * Invalid Parameter in request. - */ -#define BE_STATUS_INVALID_PARAMETER (0xE0000007L) -/* - * MessageId: BE_STATUS_NOT_SUPPORTED - * Requested operation is not supported. - */ -#define BE_STATUS_NOT_SUPPORTED (0xE000000DL) - -/* - * *************************************************************************** - * E T H E R N E T S T A T U S - * *************************************************************************** - */ - -/* - * MessageId: BE_ETH_TX_ERROR - * The Ethernet device driver failed to transmit a packet. - */ -#define BE_ETH_TX_ERROR (0xE0070101L) - -/* - * *************************************************************************** - * S H A R E D S T A T U S - * *************************************************************************** - */ - -/* - * MessageId: BE_STATUS_VBD_INVALID_VERSION - * The device driver is not compatible with this version of the VBD. - */ -#define BE_STATUS_INVALID_VERSION (0xE0070402L) -/* - * MessageId: BE_STATUS_DOMAIN_DENIED - * The operation failed to complete due to insufficient access - * rights for the requesting domain. - */ -#define BE_STATUS_DOMAIN_DENIED (0xE0070403L) -/* - * MessageId: BE_STATUS_TCP_NOT_STARTED - * The embedded TCP/IP stack has not been started. - */ -#define BE_STATUS_TCP_NOT_STARTED (0xE0070409L) -/* - * MessageId: BE_STATUS_NO_MCC_WRB - * No free MCC WRB are available for posting the request. - */ -#define BE_STATUS_NO_MCC_WRB (0xE0070414L) - -#endif /* _BESTATUS_ */ diff --git a/drivers/staging/benet/cev.h b/drivers/staging/benet/cev.h deleted file mode 100644 index 30996920a544..000000000000 --- a/drivers/staging/benet/cev.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __cev_amap_h__ -#define __cev_amap_h__ -#include "ep.h" - -/* - * Host Interrupt Status Register 0. The first of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ0 through EQ31. - */ -struct BE_CEV_ISR0_CSR_AMAP { - u8 interrupt0; /* DWORD 0 */ - u8 interrupt1; /* DWORD 0 */ - u8 interrupt2; /* DWORD 0 */ - u8 interrupt3; /* DWORD 0 */ - u8 interrupt4; /* DWORD 0 */ - u8 interrupt5; /* DWORD 0 */ - u8 interrupt6; /* DWORD 0 */ - u8 interrupt7; /* DWORD 0 */ - u8 interrupt8; /* DWORD 0 */ - u8 interrupt9; /* DWORD 0 */ - u8 interrupt10; /* DWORD 0 */ - u8 interrupt11; /* DWORD 0 */ - u8 interrupt12; /* DWORD 0 */ - u8 interrupt13; /* DWORD 0 */ - u8 interrupt14; /* DWORD 0 */ - u8 interrupt15; /* DWORD 0 */ - u8 interrupt16; /* DWORD 0 */ - u8 interrupt17; /* DWORD 0 */ - u8 interrupt18; /* DWORD 0 */ - u8 interrupt19; /* DWORD 0 */ - u8 interrupt20; /* DWORD 0 */ - u8 interrupt21; /* DWORD 0 */ - u8 interrupt22; /* DWORD 0 */ - u8 interrupt23; /* DWORD 0 */ - u8 interrupt24; /* DWORD 0 */ - u8 interrupt25; /* DWORD 0 */ - u8 interrupt26; /* DWORD 0 */ - u8 interrupt27; /* DWORD 0 */ - u8 interrupt28; /* DWORD 0 */ - u8 interrupt29; /* DWORD 0 */ - u8 interrupt30; /* DWORD 0 */ - u8 interrupt31; /* DWORD 0 */ -} __packed; -struct CEV_ISR0_CSR_AMAP { - u32 dw[1]; -}; - -/* - * Host Interrupt Status Register 1. The second of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ32 through EQ63. - */ -struct BE_CEV_ISR1_CSR_AMAP { - u8 interrupt32; /* DWORD 0 */ - u8 interrupt33; /* DWORD 0 */ - u8 interrupt34; /* DWORD 0 */ - u8 interrupt35; /* DWORD 0 */ - u8 interrupt36; /* DWORD 0 */ - u8 interrupt37; /* DWORD 0 */ - u8 interrupt38; /* DWORD 0 */ - u8 interrupt39; /* DWORD 0 */ - u8 interrupt40; /* DWORD 0 */ - u8 interrupt41; /* DWORD 0 */ - u8 interrupt42; /* DWORD 0 */ - u8 interrupt43; /* DWORD 0 */ - u8 interrupt44; /* DWORD 0 */ - u8 interrupt45; /* DWORD 0 */ - u8 interrupt46; /* DWORD 0 */ - u8 interrupt47; /* DWORD 0 */ - u8 interrupt48; /* DWORD 0 */ - u8 interrupt49; /* DWORD 0 */ - u8 interrupt50; /* DWORD 0 */ - u8 interrupt51; /* DWORD 0 */ - u8 interrupt52; /* DWORD 0 */ - u8 interrupt53; /* DWORD 0 */ - u8 interrupt54; /* DWORD 0 */ - u8 interrupt55; /* DWORD 0 */ - u8 interrupt56; /* DWORD 0 */ - u8 interrupt57; /* DWORD 0 */ - u8 interrupt58; /* DWORD 0 */ - u8 interrupt59; /* DWORD 0 */ - u8 interrupt60; /* DWORD 0 */ - u8 interrupt61; /* DWORD 0 */ - u8 interrupt62; /* DWORD 0 */ - u8 interrupt63; /* DWORD 0 */ -} __packed; -struct CEV_ISR1_CSR_AMAP { - u32 dw[1]; -}; -/* - * Host Interrupt Status Register 2. The third of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ64 through EQ95. - */ -struct BE_CEV_ISR2_CSR_AMAP { - u8 interrupt64; /* DWORD 0 */ - u8 interrupt65; /* DWORD 0 */ - u8 interrupt66; /* DWORD 0 */ - u8 interrupt67; /* DWORD 0 */ - u8 interrupt68; /* DWORD 0 */ - u8 interrupt69; /* DWORD 0 */ - u8 interrupt70; /* DWORD 0 */ - u8 interrupt71; /* DWORD 0 */ - u8 interrupt72; /* DWORD 0 */ - u8 interrupt73; /* DWORD 0 */ - u8 interrupt74; /* DWORD 0 */ - u8 interrupt75; /* DWORD 0 */ - u8 interrupt76; /* DWORD 0 */ - u8 interrupt77; /* DWORD 0 */ - u8 interrupt78; /* DWORD 0 */ - u8 interrupt79; /* DWORD 0 */ - u8 interrupt80; /* DWORD 0 */ - u8 interrupt81; /* DWORD 0 */ - u8 interrupt82; /* DWORD 0 */ - u8 interrupt83; /* DWORD 0 */ - u8 interrupt84; /* DWORD 0 */ - u8 interrupt85; /* DWORD 0 */ - u8 interrupt86; /* DWORD 0 */ - u8 interrupt87; /* DWORD 0 */ - u8 interrupt88; /* DWORD 0 */ - u8 interrupt89; /* DWORD 0 */ - u8 interrupt90; /* DWORD 0 */ - u8 interrupt91; /* DWORD 0 */ - u8 interrupt92; /* DWORD 0 */ - u8 interrupt93; /* DWORD 0 */ - u8 interrupt94; /* DWORD 0 */ - u8 interrupt95; /* DWORD 0 */ -} __packed; -struct CEV_ISR2_CSR_AMAP { - u32 dw[1]; -}; - -/* - * Host Interrupt Status Register 3. The fourth of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ96 through EQ127. - */ -struct BE_CEV_ISR3_CSR_AMAP { - u8 interrupt96; /* DWORD 0 */ - u8 interrupt97; /* DWORD 0 */ - u8 interrupt98; /* DWORD 0 */ - u8 interrupt99; /* DWORD 0 */ - u8 interrupt100; /* DWORD 0 */ - u8 interrupt101; /* DWORD 0 */ - u8 interrupt102; /* DWORD 0 */ - u8 interrupt103; /* DWORD 0 */ - u8 interrupt104; /* DWORD 0 */ - u8 interrupt105; /* DWORD 0 */ - u8 interrupt106; /* DWORD 0 */ - u8 interrupt107; /* DWORD 0 */ - u8 interrupt108; /* DWORD 0 */ - u8 interrupt109; /* DWORD 0 */ - u8 interrupt110; /* DWORD 0 */ - u8 interrupt111; /* DWORD 0 */ - u8 interrupt112; /* DWORD 0 */ - u8 interrupt113; /* DWORD 0 */ - u8 interrupt114; /* DWORD 0 */ - u8 interrupt115; /* DWORD 0 */ - u8 interrupt116; /* DWORD 0 */ - u8 interrupt117; /* DWORD 0 */ - u8 interrupt118; /* DWORD 0 */ - u8 interrupt119; /* DWORD 0 */ - u8 interrupt120; /* DWORD 0 */ - u8 interrupt121; /* DWORD 0 */ - u8 interrupt122; /* DWORD 0 */ - u8 interrupt123; /* DWORD 0 */ - u8 interrupt124; /* DWORD 0 */ - u8 interrupt125; /* DWORD 0 */ - u8 interrupt126; /* DWORD 0 */ - u8 interrupt127; /* DWORD 0 */ -} __packed; -struct CEV_ISR3_CSR_AMAP { - u32 dw[1]; -}; - -/* Completions and Events block Registers. */ -struct BE_CEV_CSRMAP_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[32]; /* DWORD 1 */ - u8 rsvd2[32]; /* DWORD 2 */ - u8 rsvd3[32]; /* DWORD 3 */ - struct BE_CEV_ISR0_CSR_AMAP isr0; - struct BE_CEV_ISR1_CSR_AMAP isr1; - struct BE_CEV_ISR2_CSR_AMAP isr2; - struct BE_CEV_ISR3_CSR_AMAP isr3; - u8 rsvd4[32]; /* DWORD 8 */ - u8 rsvd5[32]; /* DWORD 9 */ - u8 rsvd6[32]; /* DWORD 10 */ - u8 rsvd7[32]; /* DWORD 11 */ - u8 rsvd8[32]; /* DWORD 12 */ - u8 rsvd9[32]; /* DWORD 13 */ - u8 rsvd10[32]; /* DWORD 14 */ - u8 rsvd11[32]; /* DWORD 15 */ - u8 rsvd12[32]; /* DWORD 16 */ - u8 rsvd13[32]; /* DWORD 17 */ - u8 rsvd14[32]; /* DWORD 18 */ - u8 rsvd15[32]; /* DWORD 19 */ - u8 rsvd16[32]; /* DWORD 20 */ - u8 rsvd17[32]; /* DWORD 21 */ - u8 rsvd18[32]; /* DWORD 22 */ - u8 rsvd19[32]; /* DWORD 23 */ - u8 rsvd20[32]; /* DWORD 24 */ - u8 rsvd21[32]; /* DWORD 25 */ - u8 rsvd22[32]; /* DWORD 26 */ - u8 rsvd23[32]; /* DWORD 27 */ - u8 rsvd24[32]; /* DWORD 28 */ - u8 rsvd25[32]; /* DWORD 29 */ - u8 rsvd26[32]; /* DWORD 30 */ - u8 rsvd27[32]; /* DWORD 31 */ - u8 rsvd28[32]; /* DWORD 32 */ - u8 rsvd29[32]; /* DWORD 33 */ - u8 rsvd30[192]; /* DWORD 34 */ - u8 rsvd31[192]; /* DWORD 40 */ - u8 rsvd32[160]; /* DWORD 46 */ - u8 rsvd33[160]; /* DWORD 51 */ - u8 rsvd34[160]; /* DWORD 56 */ - u8 rsvd35[96]; /* DWORD 61 */ - u8 rsvd36[192][32]; /* DWORD 64 */ -} __packed; -struct CEV_CSRMAP_AMAP { - u32 dw[256]; -}; - -#endif /* __cev_amap_h__ */ diff --git a/drivers/staging/benet/cq.c b/drivers/staging/benet/cq.c deleted file mode 100644 index 650458645433..000000000000 --- a/drivers/staging/benet/cq.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include "hwlib.h" -#include "bestatus.h" - -/* - * Completion Queue Objects - */ -/* - *============================================================================ - * P U B L I C R O U T I N E S - *============================================================================ - */ - -/* - This routine creates a completion queue based on the client completion - queue configuration information. - - - FunctionObject - Handle to a function object - CqBaseVa - Base VA for a the CQ ring - NumEntries - CEV_CQ_CNT_* values - solEventEnable - 0 = All CQEs can generate Events if CQ is eventable - 1 = only CQEs with solicited bit set are eventable - eventable - Eventable CQ, generates interrupts. - nodelay - 1 = Force interrupt, relevent if CQ eventable. - Interrupt is asserted immediately after EQE - write is confirmed, regardless of EQ Timer - or watermark settings. - wme - Enable watermark based coalescing - wmThresh - High watermark(CQ fullness at which event - or interrupt should be asserted). These are the - CEV_WATERMARK encoded values. - EqObject - EQ Handle to assign to this CQ - ppCqObject - Internal CQ Handle returned. - - Returns BE_SUCCESS if successfull, otherwise a useful error code is - returned. - - IRQL < DISPATCH_LEVEL - -*/ -int be_cq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, bool solicited_eventable, - bool no_delay, u32 wm_thresh, - struct be_eq_object *eq_object, struct be_cq_object *cq_object) -{ - int status = BE_SUCCESS; - u32 num_entries_encoding; - u32 num_entries = length / sizeof(struct MCC_CQ_ENTRY_AMAP); - struct FWCMD_COMMON_CQ_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - u32 n; - unsigned long irql; - - ASSERT(rd); - ASSERT(cq_object); - ASSERT(length % sizeof(struct MCC_CQ_ENTRY_AMAP) == 0); - - switch (num_entries) { - case 256: - num_entries_encoding = CEV_CQ_CNT_256; - break; - case 512: - num_entries_encoding = CEV_CQ_CNT_512; - break; - case 1024: - num_entries_encoding = CEV_CQ_CNT_1024; - break; - default: - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - /* - * All cq entries all the same size. Use iSCSI version - * as a test for the proper rd length. - */ - memset(cq_object, 0, sizeof(*cq_object)); - - atomic_set(&cq_object->ref_count, 0); - cq_object->parent_function = pfob; - cq_object->eq_object = eq_object; - cq_object->num_entries = num_entries; - /* save for MCC cq processing */ - cq_object->va = rd->va; - - /* map into UT. */ - length = num_entries * sizeof(struct MCC_CQ_ENTRY_AMAP); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_CQ_CREATE); - - fwcmd->params.request.num_pages = PAGES_SPANNED(OFFSET_IN_PAGE(rd->va), - length); - - AMAP_SET_BITS_PTR(CQ_CONTEXT, valid, &fwcmd->params.request.context, 1); - n = pfob->pci_function_number; - AMAP_SET_BITS_PTR(CQ_CONTEXT, Func, &fwcmd->params.request.context, n); - - n = (eq_object != NULL); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Eventable, - &fwcmd->params.request.context, n); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Armed, &fwcmd->params.request.context, 1); - - n = eq_object ? eq_object->eq_id : 0; - AMAP_SET_BITS_PTR(CQ_CONTEXT, EQID, &fwcmd->params.request.context, n); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Count, - &fwcmd->params.request.context, num_entries_encoding); - - n = 0; /* Protection Domain is always 0 in Linux driver */ - AMAP_SET_BITS_PTR(CQ_CONTEXT, PD, &fwcmd->params.request.context, n); - AMAP_SET_BITS_PTR(CQ_CONTEXT, NoDelay, - &fwcmd->params.request.context, no_delay); - AMAP_SET_BITS_PTR(CQ_CONTEXT, SolEvent, - &fwcmd->params.request.context, solicited_eventable); - - n = (wm_thresh != 0xFFFFFFFF); - AMAP_SET_BITS_PTR(CQ_CONTEXT, WME, &fwcmd->params.request.context, n); - - n = (n ? wm_thresh : 0); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Watermark, - &fwcmd->params.request.context, n); - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create CQ failed."); - goto Error; - } - /* Remember the CQ id. */ - cq_object->cq_id = fwcmd->params.response.cq_id; - - /* insert this cq into eq_object reference */ - if (eq_object) { - atomic_inc(&eq_object->ref_count); - list_add_tail(&cq_object->cqlist_for_eq, - &eq_object->cq_list_head); - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - - Deferences the given object. Once the object's reference count drops to - zero, the object is destroyed and all resources that are held by this object - are released. The on-chip context is also destroyed along with the queue - ID, and any mappings made into the UT. - - cq_object - CQ handle returned from cq_object_create. - - returns the current reference count on the object - - IRQL: IRQL < DISPATCH_LEVEL -*/ -int be_cq_destroy(struct be_cq_object *cq_object) -{ - int status = 0; - - /* Nothing should reference this CQ at this point. */ - ASSERT(atomic_read(&cq_object->ref_count) == 0); - - /* Send fwcmd to destroy the CQ. */ - status = be_function_ring_destroy(cq_object->parent_function, - cq_object->cq_id, FWCMD_RING_TYPE_CQ, - NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - /* Remove reference if this is an eventable CQ. */ - if (cq_object->eq_object) { - atomic_dec(&cq_object->eq_object->ref_count); - list_del(&cq_object->cqlist_for_eq); - } - return BE_SUCCESS; -} - diff --git a/drivers/staging/benet/descriptors.h b/drivers/staging/benet/descriptors.h deleted file mode 100644 index 8da438c407d2..000000000000 --- a/drivers/staging/benet/descriptors.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __descriptors_amap_h__ -#define __descriptors_amap_h__ - -/* - * --- IPC_NODE_ID_ENUM --- - * IPC processor id values - */ -#define TPOST_NODE_ID (0) /* TPOST ID */ -#define TPRE_NODE_ID (1) /* TPRE ID */ -#define TXULP0_NODE_ID (2) /* TXULP0 ID */ -#define TXULP1_NODE_ID (3) /* TXULP1 ID */ -#define TXULP2_NODE_ID (4) /* TXULP2 ID */ -#define RXULP0_NODE_ID (5) /* RXULP0 ID */ -#define RXULP1_NODE_ID (6) /* RXULP1 ID */ -#define RXULP2_NODE_ID (7) /* RXULP2 ID */ -#define MPU_NODE_ID (15) /* MPU ID */ - -/* - * --- MAC_ID_ENUM --- - * Meaning of the mac_id field in rxpp_eth_d - */ -#define PORT0_HOST_MAC0 (0) /* PD 0, Port 0, host networking, MAC 0. */ -#define PORT0_HOST_MAC1 (1) /* PD 0, Port 0, host networking, MAC 1. */ -#define PORT0_STORAGE_MAC0 (2) /* PD 0, Port 0, host storage, MAC 0. */ -#define PORT0_STORAGE_MAC1 (3) /* PD 0, Port 0, host storage, MAC 1. */ -#define PORT1_HOST_MAC0 (4) /* PD 0, Port 1 host networking, MAC 0. */ -#define PORT1_HOST_MAC1 (5) /* PD 0, Port 1 host networking, MAC 1. */ -#define PORT1_STORAGE_MAC0 (6) /* PD 0, Port 1 host storage, MAC 0. */ -#define PORT1_STORAGE_MAC1 (7) /* PD 0, Port 1 host storage, MAC 1. */ -#define FIRST_VM_MAC (8) /* PD 1 MAC. Protection domains have IDs */ - /* from 0x8-0x26, one per PD. */ -#define LAST_VM_MAC (38) /* PD 31 MAC. */ -#define MGMT_MAC (39) /* Management port MAC. */ -#define MARBLE_MAC0 (59) /* Used for flushing function 0 receive */ - /* - * queues before re-using a torn-down - * receive ring. the DA = - * 00-00-00-00-00-00, and the MSB of the - * SA = 00 - */ -#define MARBLE_MAC1 (60) /* Used for flushing function 1 receive */ - /* - * queues before re-using a torn-down - * receive ring. the DA = - * 00-00-00-00-00-00, and the MSB of the - * SA != 00 - */ -#define NULL_MAC (61) /* Promiscuous mode, indicates no match */ -#define MCAST_MAC (62) /* Multicast match. */ -#define BCAST_MATCH (63) /* Broadcast match. */ - -#endif /* __descriptors_amap_h__ */ diff --git a/drivers/staging/benet/doorbells.h b/drivers/staging/benet/doorbells.h deleted file mode 100644 index 550cc4d5d6f7..000000000000 --- a/drivers/staging/benet/doorbells.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __doorbells_amap_h__ -#define __doorbells_amap_h__ - -/* The TX/RDMA send queue doorbell. */ -struct BE_SQ_DB_AMAP { - u8 cid[11]; /* DWORD 0 */ - u8 rsvd0[5]; /* DWORD 0 */ - u8 numPosted[14]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct SQ_DB_AMAP { - u32 dw[1]; -}; - -/* The receive queue doorbell. */ -struct BE_RQ_DB_AMAP { - u8 rq[10]; /* DWORD 0 */ - u8 rsvd0[13]; /* DWORD 0 */ - u8 Invalidate; /* DWORD 0 */ - u8 numPosted[8]; /* DWORD 0 */ -} __packed; -struct RQ_DB_AMAP { - u32 dw[1]; -}; - -/* - * The CQ/EQ doorbell. Software MUST set reserved fields in this - * descriptor to zero, otherwise (CEV) hardware will not execute the - * doorbell (flagging a bad_db_qid error instead). - */ -struct BE_CQ_DB_AMAP { - u8 qid[10]; /* DWORD 0 */ - u8 rsvd0[4]; /* DWORD 0 */ - u8 rearm; /* DWORD 0 */ - u8 event; /* DWORD 0 */ - u8 num_popped[13]; /* DWORD 0 */ - u8 rsvd1[3]; /* DWORD 0 */ -} __packed; -struct CQ_DB_AMAP { - u32 dw[1]; -}; - -struct BE_TPM_RQ_DB_AMAP { - u8 qid[10]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 numPosted[11]; /* DWORD 0 */ - u8 mss_cnt[5]; /* DWORD 0 */ -} __packed; -struct TPM_RQ_DB_AMAP { - u32 dw[1]; -}; - -/* - * Post WRB Queue Doorbell Register used by the host Storage stack - * to notify the controller of a posted Work Request Block - */ -struct BE_WRB_POST_DB_AMAP { - u8 wrb_cid[10]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 wrb_index[8]; /* DWORD 0 */ - u8 numberPosted[8]; /* DWORD 0 */ -} __packed; -struct WRB_POST_DB_AMAP { - u32 dw[1]; -}; - -/* - * Update Default PDU Queue Doorbell Register used to communicate - * to the controller that the driver has stopped processing the queue - * and where in the queue it stopped, this is - * a CQ Entry Type. Used by storage driver. - */ -struct BE_DEFAULT_PDU_DB_AMAP { - u8 qid[10]; /* DWORD 0 */ - u8 rsvd0[4]; /* DWORD 0 */ - u8 rearm; /* DWORD 0 */ - u8 event; /* DWORD 0 */ - u8 cqproc[14]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct DEFAULT_PDU_DB_AMAP { - u32 dw[1]; -}; - -/* Management Command and Controller default fragment ring */ -struct BE_MCC_DB_AMAP { - u8 rid[11]; /* DWORD 0 */ - u8 rsvd0[5]; /* DWORD 0 */ - u8 numPosted[14]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct MCC_DB_AMAP { - u32 dw[1]; -}; - -/* - * Used for bootstrapping the Host interface. This register is - * used for driver communication with the MPU when no MCC Rings exist. - * The software must write this register twice to post any MCC - * command. First, it writes the register with hi=1 and the upper bits of - * the physical address for the MCC_MAILBOX structure. Software must poll - * the ready bit until this is acknowledged. Then, sotware writes the - * register with hi=0 with the lower bits in the address. It must - * poll the ready bit until the MCC command is complete. Upon completion, - * the MCC_MAILBOX will contain a valid completion queue entry. - */ -struct BE_MPU_MAILBOX_DB_AMAP { - u8 ready; /* DWORD 0 */ - u8 hi; /* DWORD 0 */ - u8 address[30]; /* DWORD 0 */ -} __packed; -struct MPU_MAILBOX_DB_AMAP { - u32 dw[1]; -}; - -/* - * This is the protection domain doorbell register map. Note that - * while this map shows doorbells for all Blade Engine supported - * protocols, not all of these may be valid in a given function or - * protection domain. It is the responsibility of the application - * accessing the doorbells to know which are valid. Each doorbell - * occupies 32 bytes of space, but unless otherwise specified, - * only the first 4 bytes should be written. There are 32 instances - * of these doorbells for the host and 31 virtual machines respectively. - * The host and VMs will only map the doorbell pages belonging to its - * protection domain. It will not be able to touch the doorbells for - * another VM. The doorbells are the only registers directly accessible - * by a virtual machine. Similarly, there are 511 additional - * doorbells for RDMA protection domains. PD 0 for RDMA shares - * the same physical protection domain doorbell page as ETH/iSCSI. - * - */ -struct BE_PROTECTION_DOMAIN_DBMAP_AMAP { - u8 rsvd0[512]; /* DWORD 0 */ - struct BE_SQ_DB_AMAP rdma_sq_db; - u8 rsvd1[7][32]; /* DWORD 17 */ - struct BE_WRB_POST_DB_AMAP iscsi_wrb_post_db; - u8 rsvd2[7][32]; /* DWORD 25 */ - struct BE_SQ_DB_AMAP etx_sq_db; - u8 rsvd3[7][32]; /* DWORD 33 */ - struct BE_RQ_DB_AMAP rdma_rq_db; - u8 rsvd4[7][32]; /* DWORD 41 */ - struct BE_DEFAULT_PDU_DB_AMAP iscsi_default_pdu_db; - u8 rsvd5[7][32]; /* DWORD 49 */ - struct BE_TPM_RQ_DB_AMAP tpm_rq_db; - u8 rsvd6[7][32]; /* DWORD 57 */ - struct BE_RQ_DB_AMAP erx_rq_db; - u8 rsvd7[7][32]; /* DWORD 65 */ - struct BE_CQ_DB_AMAP cq_db; - u8 rsvd8[7][32]; /* DWORD 73 */ - struct BE_MCC_DB_AMAP mpu_mcc_db; - u8 rsvd9[7][32]; /* DWORD 81 */ - struct BE_MPU_MAILBOX_DB_AMAP mcc_bootstrap_db; - u8 rsvd10[935][32]; /* DWORD 89 */ -} __packed; -struct PROTECTION_DOMAIN_DBMAP_AMAP { - u32 dw[1024]; -}; - -#endif /* __doorbells_amap_h__ */ diff --git a/drivers/staging/benet/ep.h b/drivers/staging/benet/ep.h deleted file mode 100644 index 72fcf64a9ffb..000000000000 --- a/drivers/staging/benet/ep.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __ep_amap_h__ -#define __ep_amap_h__ - -/* General Control and Status Register. */ -struct BE_EP_CONTROL_CSR_AMAP { - u8 m0_RxPbuf; /* DWORD 0 */ - u8 m1_RxPbuf; /* DWORD 0 */ - u8 m2_RxPbuf; /* DWORD 0 */ - u8 ff_en; /* DWORD 0 */ - u8 rsvd0[27]; /* DWORD 0 */ - u8 CPU_reset; /* DWORD 0 */ -} __packed; -struct EP_CONTROL_CSR_AMAP { - u32 dw[1]; -}; - -/* Semaphore Register. */ -struct BE_EP_SEMAPHORE_CSR_AMAP { - u8 value[32]; /* DWORD 0 */ -} __packed; -struct EP_SEMAPHORE_CSR_AMAP { - u32 dw[1]; -}; - -/* Embedded Processor Specific Registers. */ -struct BE_EP_CSRMAP_AMAP { - struct BE_EP_CONTROL_CSR_AMAP ep_control; - u8 rsvd0[32]; /* DWORD 1 */ - u8 rsvd1[32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 3 */ - u8 rsvd3[32]; /* DWORD 4 */ - u8 rsvd4[32]; /* DWORD 5 */ - u8 rsvd5[8][128]; /* DWORD 6 */ - u8 rsvd6[32]; /* DWORD 38 */ - u8 rsvd7[32]; /* DWORD 39 */ - u8 rsvd8[32]; /* DWORD 40 */ - u8 rsvd9[32]; /* DWORD 41 */ - u8 rsvd10[32]; /* DWORD 42 */ - struct BE_EP_SEMAPHORE_CSR_AMAP ep_semaphore; - u8 rsvd11[32]; /* DWORD 44 */ - u8 rsvd12[19][32]; /* DWORD 45 */ -} __packed; -struct EP_CSRMAP_AMAP { - u32 dw[64]; -}; - -#endif /* __ep_amap_h__ */ diff --git a/drivers/staging/benet/eq.c b/drivers/staging/benet/eq.c deleted file mode 100644 index db92ccd8fed8..000000000000 --- a/drivers/staging/benet/eq.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include "hwlib.h" -#include "bestatus.h" -/* - This routine creates an event queue based on the client completion - queue configuration information. - - FunctionObject - Handle to a function object - EqBaseVa - Base VA for a the EQ ring - SizeEncoding - The encoded size for the EQ entries. This value is - either CEV_EQ_SIZE_4 or CEV_EQ_SIZE_16 - NumEntries - CEV_CQ_CNT_* values. - Watermark - Enables watermark based coalescing. This parameter - must be of the type CEV_WMARK_* if watermarks - are enabled. If watermarks to to be disabled - this value should be-1. - TimerDelay - If a timer delay is enabled this value should be the - time of the delay in 8 microsecond units. If - delays are not used this parameter should be - set to -1. - ppEqObject - Internal EQ Handle returned. - - Returns BE_SUCCESS if successfull,, otherwise a useful error code - is returned. - - IRQL < DISPATCH_LEVEL -*/ -int -be_eq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 eqe_size, u32 num_entries, - u32 watermark, /* CEV_WMARK_* or -1 */ - u32 timer_delay, /* in 8us units, or -1 */ - struct be_eq_object *eq_object) -{ - int status = BE_SUCCESS; - u32 num_entries_encoding, eqe_size_encoding, length; - struct FWCMD_COMMON_EQ_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - u32 n; - unsigned long irql; - - ASSERT(rd); - ASSERT(eq_object); - - switch (num_entries) { - case 256: - num_entries_encoding = CEV_EQ_CNT_256; - break; - case 512: - num_entries_encoding = CEV_EQ_CNT_512; - break; - case 1024: - num_entries_encoding = CEV_EQ_CNT_1024; - break; - case 2048: - num_entries_encoding = CEV_EQ_CNT_2048; - break; - case 4096: - num_entries_encoding = CEV_EQ_CNT_4096; - break; - default: - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - switch (eqe_size) { - case 4: - eqe_size_encoding = CEV_EQ_SIZE_4; - break; - case 16: - eqe_size_encoding = CEV_EQ_SIZE_16; - break; - default: - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - if ((eqe_size == 4 && num_entries < 1024) || - (eqe_size == 16 && num_entries == 4096)) { - TRACE(DL_ERR, "Bad EQ size. eqe_size:%d num_entries:%d", - eqe_size, num_entries); - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - memset(eq_object, 0, sizeof(*eq_object)); - - atomic_set(&eq_object->ref_count, 0); - eq_object->parent_function = pfob; - eq_object->eq_id = 0xFFFFFFFF; - - INIT_LIST_HEAD(&eq_object->cq_list_head); - - length = num_entries * eqe_size; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_EQ_CREATE); - - fwcmd->params.request.num_pages = PAGES_SPANNED(OFFSET_IN_PAGE(rd->va), - length); - n = pfob->pci_function_number; - AMAP_SET_BITS_PTR(EQ_CONTEXT, Func, &fwcmd->params.request.context, n); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, valid, &fwcmd->params.request.context, 1); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, Size, - &fwcmd->params.request.context, eqe_size_encoding); - - n = 0; /* Protection Domain is always 0 in Linux driver */ - AMAP_SET_BITS_PTR(EQ_CONTEXT, PD, &fwcmd->params.request.context, n); - - /* Let the caller ARM the EQ with the doorbell. */ - AMAP_SET_BITS_PTR(EQ_CONTEXT, Armed, &fwcmd->params.request.context, 0); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, Count, &fwcmd->params.request.context, - num_entries_encoding); - - n = pfob->pci_function_number * 32; - AMAP_SET_BITS_PTR(EQ_CONTEXT, EventVect, - &fwcmd->params.request.context, n); - if (watermark != -1) { - AMAP_SET_BITS_PTR(EQ_CONTEXT, WME, - &fwcmd->params.request.context, 1); - AMAP_SET_BITS_PTR(EQ_CONTEXT, Watermark, - &fwcmd->params.request.context, watermark); - ASSERT(watermark <= CEV_WMARK_240); - } else - AMAP_SET_BITS_PTR(EQ_CONTEXT, WME, - &fwcmd->params.request.context, 0); - if (timer_delay != -1) { - AMAP_SET_BITS_PTR(EQ_CONTEXT, TMR, - &fwcmd->params.request.context, 1); - - ASSERT(timer_delay <= 250); /* max value according to EAS */ - timer_delay = min(timer_delay, (u32)250); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, Delay, - &fwcmd->params.request.context, timer_delay); - } else { - AMAP_SET_BITS_PTR(EQ_CONTEXT, TMR, - &fwcmd->params.request.context, 0); - } - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create EQ failed."); - goto Error; - } - /* Get the EQ id. The MPU allocates the IDs. */ - eq_object->eq_id = fwcmd->params.response.eq_id; - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - Deferences the given object. Once the object's reference count drops to - zero, the object is destroyed and all resources that are held by this - object are released. The on-chip context is also destroyed along with - the queue ID, and any mappings made into the UT. - - eq_object - EQ handle returned from eq_object_create. - - Returns BE_SUCCESS if successfull, otherwise a useful error code - is returned. - - IRQL: IRQL < DISPATCH_LEVEL -*/ -int be_eq_destroy(struct be_eq_object *eq_object) -{ - int status = 0; - - ASSERT(atomic_read(&eq_object->ref_count) == 0); - /* no CQs should reference this EQ now */ - ASSERT(list_empty(&eq_object->cq_list_head)); - - /* Send fwcmd to destroy the EQ. */ - status = be_function_ring_destroy(eq_object->parent_function, - eq_object->eq_id, FWCMD_RING_TYPE_EQ, - NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - return BE_SUCCESS; -} -/* - *--------------------------------------------------------------------------- - * Function: be_eq_modify_delay - * Changes the EQ delay for a group of EQs. - * num_eq - The number of EQs in the eq_array to adjust. - * This also is the number of delay values in - * the eq_delay_array. - * eq_array - Array of struct be_eq_object pointers to adjust. - * eq_delay_array - Array of "num_eq" timer delays in units - * of microseconds. The be_eq_query_delay_range - * fwcmd returns the resolution and range of - * legal EQ delays. - * cb - - * cb_context - - * q_ctxt - Optional. Pointer to a previously allocated - * struct. If the MCC WRB ring is full, this - * structure is used to queue the operation. It - * will be posted to the MCC ring when space - * becomes available. All queued commands will - * be posted to the ring in the order they are - * received. It is always valid to pass a pointer to - * a generic be_generic_q_cntxt. However, - * the specific context structs - * are generally smaller than the generic struct. - * return pend_status - BE_SUCCESS (0) on success. - * BE_PENDING (postive value) if the FWCMD - * completion is pending. Negative error code on failure. - *------------------------------------------------------------------------- - */ -int -be_eq_modify_delay(struct be_function_object *pfob, - u32 num_eq, struct be_eq_object **eq_array, - u32 *eq_delay_array, mcc_wrb_cqe_callback cb, - void *cb_context, struct be_eq_modify_delay_q_ctxt *q_ctxt) -{ - struct FWCMD_COMMON_MODIFY_EQ_DELAY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *gen_ctxt = NULL; - u32 i; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - gen_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - gen_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_MODIFY_EQ_DELAY); - - ASSERT(num_eq > 0); - ASSERT(num_eq <= ARRAY_SIZE(fwcmd->params.request.delay)); - fwcmd->params.request.num_eq = num_eq; - for (i = 0; i < num_eq; i++) { - fwcmd->params.request.delay[i].eq_id = eq_array[i]->eq_id; - fwcmd->params.request.delay[i].delay_in_microseconds = - eq_delay_array[i]; - } - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, gen_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - diff --git a/drivers/staging/benet/eth.c b/drivers/staging/benet/eth.c deleted file mode 100644 index f641b6260d07..000000000000 --- a/drivers/staging/benet/eth.c +++ /dev/null @@ -1,1273 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include -#include "hwlib.h" -#include "bestatus.h" - -/* - *--------------------------------------------------------- - * Function: be_eth_sq_create_ex - * Creates an ethernet send ring - extended version with - * additional parameters. - * pfob - - * rd - ring address - * length_in_bytes - - * type - The type of ring to create. - * ulp - The requested ULP number for the ring. - * This should be zero based, i.e. 0,1,2. This must - * be valid NIC ULP based on the firmware config. - * All doorbells for this ring must be sent to - * this ULP. The first network ring allocated for - * each ULP are higher performance than subsequent rings. - * cq_object - cq object for completions - * ex_parameters - Additional parameters (that may increase in - * future revisions). These parameters are only used - * for certain ring types -- see - * struct be_eth_sq_parameters for details. - * eth_sq - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_sq_create_ex(struct be_function_object *pfob, struct ring_desc *rd, - u32 length, u32 type, u32 ulp, struct be_cq_object *cq_object, - struct be_eth_sq_parameters *ex_parameters, - struct be_ethsq_object *eth_sq) -{ - struct FWCMD_COMMON_ETH_TX_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - u32 n; - unsigned long irql; - - ASSERT(rd); - ASSERT(eth_sq); - ASSERT(ex_parameters); - - spin_lock_irqsave(&pfob->post_lock, irql); - - memset(eth_sq, 0, sizeof(*eth_sq)); - - eth_sq->parent_function = pfob; - eth_sq->bid = 0xFFFFFFFF; - eth_sq->cq_object = cq_object; - - /* Translate hwlib interface to arm interface. */ - switch (type) { - case BE_ETH_TX_RING_TYPE_FORWARDING: - type = ETH_TX_RING_TYPE_FORWARDING; - break; - case BE_ETH_TX_RING_TYPE_STANDARD: - type = ETH_TX_RING_TYPE_STANDARD; - break; - case BE_ETH_TX_RING_TYPE_BOUND: - ASSERT(ex_parameters->port < 2); - type = ETH_TX_RING_TYPE_BOUND; - break; - default: - TRACE(DL_ERR, "Invalid eth tx ring type:%d", type); - return BE_NOT_OK; - break; - } - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* NIC must be supported by the current config. */ - ASSERT(pfob->fw_config.nic_ulp_mask); - - /* - * The ulp parameter must select a valid NIC ULP - * for the current config. - */ - ASSERT((1 << ulp) & pfob->fw_config.nic_ulp_mask); - - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_ETH_TX_CREATE); - fwcmd->header.request.port_number = ex_parameters->port; - - AMAP_SET_BITS_PTR(ETX_CONTEXT, pd_id, - &fwcmd->params.request.context, 0); - - n = be_ring_length_to_encoding(length, sizeof(struct ETH_WRB_AMAP)); - AMAP_SET_BITS_PTR(ETX_CONTEXT, tx_ring_size, - &fwcmd->params.request.context, n); - - AMAP_SET_BITS_PTR(ETX_CONTEXT, cq_id_send, - &fwcmd->params.request.context, cq_object->cq_id); - - n = pfob->pci_function_number; - AMAP_SET_BITS_PTR(ETX_CONTEXT, func, &fwcmd->params.request.context, n); - - fwcmd->params.request.type = type; - fwcmd->params.request.ulp_num = (1 << ulp); - fwcmd->params.request.num_pages = DIV_ROUND_UP(length, PAGE_SIZE); - ASSERT(PAGES_SPANNED(rd->va, rd->length) >= - fwcmd->params.request.num_pages); - - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create etx queue failed."); - goto Error; - } - /* save the butler ID */ - eth_sq->bid = fwcmd->params.response.cid; - - /* add a reference to the corresponding CQ */ - atomic_inc(&cq_object->ref_count); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - This routine destroys an ethernet send queue - - EthSq - EthSq Handle returned from EthSqCreate - - This function always return BE_SUCCESS. - - This function frees memory allocated by EthSqCreate for the EthSq Object. - -*/ -int be_eth_sq_destroy(struct be_ethsq_object *eth_sq) -{ - int status = 0; - - /* Send fwcmd to destroy the queue. */ - status = be_function_ring_destroy(eth_sq->parent_function, eth_sq->bid, - FWCMD_RING_TYPE_ETH_TX, NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - /* Derefence any associated CQs. */ - atomic_dec(ð_sq->cq_object->ref_count); - return status; -} -/* - This routine attempts to set the transmit flow control parameters. - - FunctionObject - Handle to a function object - - txfc_enable - transmit flow control enable - true for - enable, false for disable - - rxfc_enable - receive flow control enable - true for - enable, false for disable - - Returns BE_SUCCESS if successfull, otherwise a useful int error - code is returned. - - IRQL: < DISPATCH_LEVEL - - This function always fails in non-privileged machine context. -*/ -int -be_eth_set_flow_control(struct be_function_object *pfob, - bool txfc_enable, bool rxfc_enable) -{ - struct FWCMD_COMMON_SET_FLOW_CONTROL *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_FLOW_CONTROL); - - fwcmd->params.request.rx_flow_control = rxfc_enable; - fwcmd->params.request.tx_flow_control = txfc_enable; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "set flow control fwcmd failed."); - goto error; - } - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine attempts to get the transmit flow control parameters. - - pfob - Handle to a function object - - txfc_enable - transmit flow control enable - true for - enable, false for disable - - rxfc_enable - receive flow control enable - true for enable, - false for disable - - Returns BE_SUCCESS if successfull, otherwise a useful int error code - is returned. - - IRQL: < DISPATCH_LEVEL - - This function always fails in non-privileged machine context. -*/ -int -be_eth_get_flow_control(struct be_function_object *pfob, - bool *txfc_enable, bool *rxfc_enable) -{ - struct FWCMD_COMMON_GET_FLOW_CONTROL *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_FLOW_CONTROL); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "get flow control fwcmd failed."); - goto error; - } - - *txfc_enable = fwcmd->params.response.tx_flow_control; - *rxfc_enable = fwcmd->params.response.rx_flow_control; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - *--------------------------------------------------------- - * Function: be_eth_set_qos - * This function sets the ethernet transmit Quality of Service (QoS) - * characteristics of BladeEngine for the domain. All ethernet - * transmit rings of the domain will evenly share the bandwidth. - * The exeception to sharing is the host primary (super) ethernet - * transmit ring as well as the host ethernet forwarding ring - * for missed offload data. - * pfob - - * max_bps - the maximum bits per second in units of - * 10 Mbps (valid 0-100) - * max_pps - the maximum packets per second in units - * of 1 Kpps (0 indicates no limit) - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_set_qos(struct be_function_object *pfob, u32 max_bps, u32 max_pps) -{ - struct FWCMD_COMMON_SET_QOS *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_QOS); - - /* Set fields in fwcmd */ - fwcmd->params.request.max_bits_per_second_NIC = max_bps; - fwcmd->params.request.max_packets_per_second_NIC = max_pps; - fwcmd->params.request.valid_flags = QOS_BITS_NIC | QOS_PKTS_NIC; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) - TRACE(DL_ERR, "network set qos fwcmd failed."); - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - *--------------------------------------------------------- - * Function: be_eth_get_qos - * This function retrieves the ethernet transmit Quality of Service (QoS) - * characteristics for the domain. - * max_bps - the maximum bits per second in units of - * 10 Mbps (valid 0-100) - * max_pps - the maximum packets per second in units of - * 1 Kpps (0 indicates no limit) - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_get_qos(struct be_function_object *pfob, u32 *max_bps, u32 *max_pps) -{ - struct FWCMD_COMMON_GET_QOS *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_QOS); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "network get qos fwcmd failed."); - goto error; - } - - *max_bps = fwcmd->params.response.max_bits_per_second_NIC; - *max_pps = fwcmd->params.response.max_packets_per_second_NIC; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - *--------------------------------------------------------- - * Function: be_eth_set_frame_size - * This function sets the ethernet maximum frame size. The previous - * values are returned. - * pfob - - * tx_frame_size - maximum transmit frame size in bytes - * rx_frame_size - maximum receive frame size in bytes - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_set_frame_size(struct be_function_object *pfob, - u32 *tx_frame_size, u32 *rx_frame_size) -{ - struct FWCMD_COMMON_SET_FRAME_SIZE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_FRAME_SIZE); - fwcmd->params.request.max_tx_frame_size = *tx_frame_size; - fwcmd->params.request.max_rx_frame_size = *rx_frame_size; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "network set frame size fwcmd failed."); - goto error; - } - - *tx_frame_size = fwcmd->params.response.chip_max_tx_frame_size; - *rx_frame_size = fwcmd->params.response.chip_max_rx_frame_size; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - This routine creates a Ethernet receive ring. - - pfob - handle to a function object - rq_base_va - base VA for the default receive ring. this must be - exactly 8K in length and continguous physical memory. - cq_object - handle to a previously created CQ to be associated - with the RQ. - pp_eth_rq - pointer to an opqaue handle where an eth - receive object is returned. - Returns BE_SUCCESS if successfull, , otherwise a useful - int error code is returned. - - IRQL: < DISPATCH_LEVEL - this function allocates a struct be_ethrq_object *object. - there must be no more than 1 of these per function object, unless the - function object supports RSS (is networking and on the host). - the rq_base_va must point to a buffer of exactly 8K. - the erx::host_cqid (or host_stor_cqid) register and erx::ring_page registers - will be updated as appropriate on return -*/ -int -be_eth_rq_create(struct be_function_object *pfob, - struct ring_desc *rd, struct be_cq_object *cq_object, - struct be_cq_object *bcmc_cq_object, - struct be_ethrq_object *eth_rq) -{ - int status = 0; - struct MCC_WRB_AMAP *wrb = NULL; - struct FWCMD_COMMON_ETH_RX_CREATE *fwcmd = NULL; - unsigned long irql; - - /* MPU will set the */ - ASSERT(rd); - ASSERT(eth_rq); - - spin_lock_irqsave(&pfob->post_lock, irql); - - eth_rq->parent_function = pfob; - eth_rq->cq_object = cq_object; - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_ETH_RX_CREATE); - - fwcmd->params.request.num_pages = 2; /* required length */ - fwcmd->params.request.cq_id = cq_object->cq_id; - - if (bcmc_cq_object) - fwcmd->params.request.bcmc_cq_id = bcmc_cq_object->cq_id; - else - fwcmd->params.request.bcmc_cq_id = 0xFFFF; - - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "fwcmd to map eth rxq frags failed."); - goto Error; - } - /* Save the ring ID for cleanup. */ - eth_rq->rid = fwcmd->params.response.id; - - atomic_inc(&cq_object->ref_count); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine destroys an Ethernet receive queue - - eth_rq - ethernet receive queue handle returned from eth_rq_create - - Returns BE_SUCCESS on success and an appropriate int on failure. - - This function frees resourcs allocated by EthRqCreate. - The erx::host_cqid (or host_stor_cqid) register and erx::ring_page - registers will be updated as appropriate on return - IRQL: < DISPATCH_LEVEL -*/ - -static void be_eth_rq_destroy_internal_cb(void *context, int status, - struct MCC_WRB_AMAP *wrb) -{ - struct be_ethrq_object *eth_rq = (struct be_ethrq_object *) context; - - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "Destroy eth rq failed in internal callback.\n"); - } else { - /* Dereference any CQs associated with this queue. */ - atomic_dec(ð_rq->cq_object->ref_count); - } - - return; -} - -int be_eth_rq_destroy(struct be_ethrq_object *eth_rq) -{ - int status = BE_SUCCESS; - - /* Send fwcmd to destroy the RQ. */ - status = be_function_ring_destroy(eth_rq->parent_function, - eth_rq->rid, FWCMD_RING_TYPE_ETH_RX, NULL, NULL, - be_eth_rq_destroy_internal_cb, eth_rq); - - return status; -} - -/* - *--------------------------------------------------------------------------- - * Function: be_eth_rq_destroy_options - * Destroys an ethernet receive ring with finer granularity options - * than the standard be_eth_rq_destroy() API function. - * eth_rq - - * flush - Set to 1 to flush the ring, set to 0 to bypass the flush - * cb - Callback function on completion - * cb_context - Callback context - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *---------------------------------------------------------------------------- - */ -int -be_eth_rq_destroy_options(struct be_ethrq_object *eth_rq, bool flush, - mcc_wrb_cqe_callback cb, void *cb_context) -{ - struct FWCMD_COMMON_RING_DESTROY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = BE_SUCCESS; - struct be_function_object *pfob = NULL; - unsigned long irql; - - pfob = eth_rq->parent_function; - - spin_lock_irqsave(&pfob->post_lock, irql); - - TRACE(DL_INFO, "Destroy eth_rq ring id:%d, flush:%d", eth_rq->rid, - flush); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in destroy eth_rq ring."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_RING_DESTROY); - - fwcmd->params.request.id = eth_rq->rid; - fwcmd->params.request.ring_type = FWCMD_RING_TYPE_ETH_RX; - fwcmd->params.request.bypass_flush = ((0 == flush) ? 1 : 0); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, cb_context, - be_eth_rq_destroy_internal_cb, eth_rq, fwcmd, NULL); - - if (status != BE_SUCCESS && status != BE_PENDING) { - TRACE(DL_ERR, "eth_rq ring destroy failed. id:%d, flush:%d", - eth_rq->rid, flush); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine queries the frag size for erx. - - pfob - handle to a function object - - frag_size_bytes - erx frag size in bytes that is/was set. - - Returns BE_SUCCESS if successfull, otherwise a useful int error - code is returned. - - IRQL: < DISPATCH_LEVEL - -*/ -int -be_eth_rq_get_frag_size(struct be_function_object *pfob, u32 *frag_size_bytes) -{ - struct FWCMD_ETH_GET_RX_FRAG_SIZE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - ASSERT(frag_size_bytes); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - return BE_STATUS_NO_MCC_WRB; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_GET_RX_FRAG_SIZE); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "get frag size fwcmd failed."); - goto error; - } - - *frag_size_bytes = 1 << fwcmd->params.response.actual_fragsize_log2; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine attempts to set the frag size for erx. If the frag size is - already set, the attempt fails and the current frag size is returned. - - pfob - Handle to a function object - - frag_size - Erx frag size in bytes that is/was set. - - current_frag_size_bytes - Pointer to location where currrent frag - is to be rturned - - Returns BE_SUCCESS if successfull, otherwise a useful int error - code is returned. - - IRQL: < DISPATCH_LEVEL - - This function always fails in non-privileged machine context. -*/ -int -be_eth_rq_set_frag_size(struct be_function_object *pfob, - u32 frag_size, u32 *frag_size_bytes) -{ - struct FWCMD_ETH_SET_RX_FRAG_SIZE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - ASSERT(frag_size_bytes); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_SET_RX_FRAG_SIZE); - - ASSERT(frag_size >= 128 && frag_size <= 16 * 1024); - - /* This is the log2 of the fragsize. This is not the exact - * ERX encoding. */ - fwcmd->params.request.new_fragsize_log2 = __ilog2_u32(frag_size); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "set frag size fwcmd failed."); - goto error; - } - - *frag_size_bytes = 1 << fwcmd->params.response.actual_fragsize_log2; -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - This routine gets or sets a mac address for a domain - given the port and mac. - - FunctionObject - Function object handle. - port1 - Set to TRUE if this function will set/get the Port 1 - address. Only the host may set this to TRUE. - mac1 - Set to TRUE if this function will set/get the - MAC 1 address. Only the host may set this to TRUE. - write - Set to TRUE if this function should write the mac address. - mac_address - Buffer of the mac address to read or write. - - Returns BE_SUCCESS if successfull, otherwise a useful int is returned. - - IRQL: < DISPATCH_LEVEL -*/ -int be_rxf_mac_address_read_write(struct be_function_object *pfob, - bool port1, /* VM must always set to false */ - bool mac1, /* VM must always set to false */ - bool mgmt, bool write, - bool permanent, u8 *mac_address, - mcc_wrb_cqe_callback cb, /* optional */ - void *cb_context) /* optional */ -{ - int status = BE_SUCCESS; - union { - struct FWCMD_COMMON_NTWK_MAC_QUERY *query; - struct FWCMD_COMMON_NTWK_MAC_SET *set; - } fwcmd = {NULL}; - struct MCC_WRB_AMAP *wrb = NULL; - u32 type = 0; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - spin_lock_irqsave(&pfob->post_lock, irql); - - ASSERT(mac_address); - - ASSERT(port1 == false); - ASSERT(mac1 == false); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - - if (mgmt) { - type = MAC_ADDRESS_TYPE_MANAGEMENT; - } else { - if (pfob->type == BE_FUNCTION_TYPE_NETWORK) - type = MAC_ADDRESS_TYPE_NETWORK; - else - type = MAC_ADDRESS_TYPE_STORAGE; - } - - if (write) { - /* Prepares an embedded fwcmd, including - * request/response sizes. - */ - fwcmd.set = BE_PREPARE_EMBEDDED_FWCMD(pfob, - wrb, COMMON_NTWK_MAC_SET); - - fwcmd.set->params.request.invalidate = 0; - fwcmd.set->params.request.mac1 = (mac1 ? 1 : 0); - fwcmd.set->params.request.port = (port1 ? 1 : 0); - fwcmd.set->params.request.type = type; - - /* Copy the mac address to set. */ - fwcmd.set->params.request.mac.SizeOfStructure = - sizeof(fwcmd.set->params.request.mac); - memcpy(fwcmd.set->params.request.mac.MACAddress, - mac_address, ETH_ALEN); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, - cb, cb_context, NULL, NULL, fwcmd.set, NULL); - - } else { - - /* - * Prepares an embedded fwcmd, including - * request/response sizes. - */ - fwcmd.query = BE_PREPARE_EMBEDDED_FWCMD(pfob, - wrb, COMMON_NTWK_MAC_QUERY); - - fwcmd.query->params.request.mac1 = (mac1 ? 1 : 0); - fwcmd.query->params.request.port = (port1 ? 1 : 0); - fwcmd.query->params.request.type = type; - fwcmd.query->params.request.permanent = permanent; - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_MAC_QUERY, - params.response.mac.MACAddress); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_MAC_QUERY, - params.response.mac.MACAddress); - rc.va = mac_address; - /* Post the f/w command (with a copy for the response) */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, - cb_context, NULL, NULL, fwcmd.query, &rc); - } - - if (status < 0) { - TRACE(DL_ERR, "mac set/query failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine writes data to context memory. - - pfob - Function object handle. - mac_table - Set to the 128-bit multicast address hash table. - - Returns BE_SUCCESS if successfull, otherwise a useful int is returned. - - IRQL: < DISPATCH_LEVEL -*/ - -int be_rxf_multicast_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u8 *mac_table, - mcc_wrb_cqe_callback cb, /* optional */ - void *cb_context, - struct be_multicast_q_ctxt *q_ctxt) -{ - int status = BE_SUCCESS; - struct FWCMD_COMMON_NTWK_MULTICAST_SET *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - ASSERT(num <= ARRAY_SIZE(fwcmd->params.request.mac)); - - if (num > ARRAY_SIZE(fwcmd->params.request.mac)) { - TRACE(DL_ERR, "Too many multicast addresses. BE supports %d.", - (int) ARRAY_SIZE(fwcmd->params.request.mac)); - return BE_NOT_OK; - } - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_MULTICAST_SET); - - fwcmd->params.request.promiscuous = promiscuous; - if (!promiscuous) { - fwcmd->params.request.num_mac = num; - if (num > 0) { - ASSERT(mac_table); - memcpy(fwcmd->params.request.mac, - mac_table, ETH_ALEN * num); - } - } - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - if (status < 0) { - TRACE(DL_ERR, "multicast fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine adds or removes a vlan tag from the rxf table. - - FunctionObject - Function object handle. - VLanTag - VLan tag to add or remove. - Add - Set to TRUE if this will add a vlan tag - - Returns BE_SUCCESS if successfull, otherwise a useful int is returned. - - IRQL: < DISPATCH_LEVEL -*/ -int be_rxf_vlan_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u16 *vlan_tag_array, - mcc_wrb_cqe_callback cb, /* optional */ - void *cb_context, - struct be_vlan_q_ctxt *q_ctxt) /* optional */ -{ - int status = BE_SUCCESS; - struct FWCMD_COMMON_NTWK_VLAN_CONFIG *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - if (num > ARRAY_SIZE(fwcmd->params.request.vlan_tag)) { - TRACE(DL_ERR, "Too many VLAN tags."); - return BE_NOT_OK; - } - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_VLAN_CONFIG); - - fwcmd->params.request.promiscuous = promiscuous; - if (!promiscuous) { - fwcmd->params.request.num_vlan = num; - - if (num > 0) { - ASSERT(vlan_tag_array); - memcpy(fwcmd->params.request.vlan_tag, vlan_tag_array, - num * sizeof(vlan_tag_array[0])); - } - } - - /* Post the commadn */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - if (status < 0) { - TRACE(DL_ERR, "vlan fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -int be_rxf_link_status(struct be_function_object *pfob, - struct BE_LINK_STATUS *link_status, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_link_status_q_ctxt *q_ctxt) -{ - struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - ASSERT(link_status); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, - COMMON_NTWK_LINK_STATUS_QUERY); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY, - params.response); - rc.va = link_status; - /* Post or queue the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, &rc); - - if (status < 0) { - TRACE(DL_ERR, "link status fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -int -be_rxf_query_eth_statistics(struct be_function_object *pfob, - struct FWCMD_ETH_GET_STATISTICS *va_for_fwcmd, - u64 pa_for_fwcmd, mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_nonembedded_q_ctxt *q_ctxt) -{ - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - ASSERT(va_for_fwcmd); - ASSERT(pa_for_fwcmd); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - - TRACE(DL_INFO, "Query eth stats. fwcmd va:%p pa:0x%08x_%08x", - va_for_fwcmd, upper_32_bits(pa_for_fwcmd), (u32)pa_for_fwcmd); - - /* Prepares an embedded fwcmd, including request/response sizes. */ - va_for_fwcmd = BE_PREPARE_NONEMBEDDED_FWCMD(pfob, wrb, - va_for_fwcmd, pa_for_fwcmd, ETH_GET_STATISTICS); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, va_for_fwcmd, NULL); - if (status < 0) { - TRACE(DL_ERR, "eth stats fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -int -be_rxf_promiscuous(struct be_function_object *pfob, - bool enable_port0, bool enable_port1, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_promiscuous_q_ctxt *q_ctxt) -{ - struct FWCMD_ETH_PROMISCUOUS *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_PROMISCUOUS); - - fwcmd->params.request.port0_promiscuous = enable_port0; - fwcmd->params.request.port1_promiscuous = enable_port1; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - - if (status < 0) { - TRACE(DL_ERR, "promiscuous fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - *------------------------------------------------------------------------- - * Function: be_rxf_filter_config - * Configures BladeEngine ethernet receive filter settings. - * pfob - - * settings - Pointer to the requested filter settings. - * The response from BladeEngine will be placed back - * in this structure. - * cb - optional - * cb_context - optional - * q_ctxt - Optional. Pointer to a previously allocated struct. - * If the MCC WRB ring is full, this structure is - * used to queue the operation. It will be posted - * to the MCC ring when space becomes available. All - * queued commands will be posted to the ring in - * the order they are received. It is always valid - * to pass a pointer to a generic - * be_generic_q_ctxt. However, the specific - * context structs are generally smaller than - * the generic struct. - * return pend_status - BE_SUCCESS (0) on success. - * BE_PENDING (postive value) if the FWCMD - * completion is pending. Negative error code on failure. - *--------------------------------------------------------------------------- - */ -int -be_rxf_filter_config(struct be_function_object *pfob, - struct NTWK_RX_FILTER_SETTINGS *settings, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_rxf_filter_q_ctxt *q_ctxt) -{ - struct FWCMD_COMMON_NTWK_RX_FILTER *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - ASSERT(settings); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_RX_FILTER); - memcpy(&fwcmd->params.request, settings, sizeof(*settings)); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_RX_FILTER, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_RX_FILTER, - params.response); - rc.va = settings; - /* Post or queue the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, &rc); - - if (status < 0) { - TRACE(DL_ERR, "RXF/ERX filter config fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} diff --git a/drivers/staging/benet/etx_context.h b/drivers/staging/benet/etx_context.h deleted file mode 100644 index 554fbe5d127b..000000000000 --- a/drivers/staging/benet/etx_context.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __etx_context_amap_h__ -#define __etx_context_amap_h__ - -/* ETX ring context structure. */ -struct BE_ETX_CONTEXT_AMAP { - u8 tx_cidx[11]; /* DWORD 0 */ - u8 rsvd0[5]; /* DWORD 0 */ - u8 rsvd1[16]; /* DWORD 0 */ - u8 tx_pidx[11]; /* DWORD 1 */ - u8 rsvd2; /* DWORD 1 */ - u8 tx_ring_size[4]; /* DWORD 1 */ - u8 pd_id[5]; /* DWORD 1 */ - u8 pd_id_not_valid; /* DWORD 1 */ - u8 cq_id_send[10]; /* DWORD 1 */ - u8 rsvd3[32]; /* DWORD 2 */ - u8 rsvd4[32]; /* DWORD 3 */ - u8 cur_bytes[32]; /* DWORD 4 */ - u8 max_bytes[32]; /* DWORD 5 */ - u8 time_stamp[32]; /* DWORD 6 */ - u8 rsvd5[11]; /* DWORD 7 */ - u8 func; /* DWORD 7 */ - u8 rsvd6[20]; /* DWORD 7 */ - u8 cur_txd_count[32]; /* DWORD 8 */ - u8 max_txd_count[32]; /* DWORD 9 */ - u8 rsvd7[32]; /* DWORD 10 */ - u8 rsvd8[32]; /* DWORD 11 */ - u8 rsvd9[32]; /* DWORD 12 */ - u8 rsvd10[32]; /* DWORD 13 */ - u8 rsvd11[32]; /* DWORD 14 */ - u8 rsvd12[32]; /* DWORD 15 */ -} __packed; -struct ETX_CONTEXT_AMAP { - u32 dw[16]; -}; - -#endif /* __etx_context_amap_h__ */ diff --git a/drivers/staging/benet/funcobj.c b/drivers/staging/benet/funcobj.c deleted file mode 100644 index 0f57eb58daef..000000000000 --- a/drivers/staging/benet/funcobj.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include "hwlib.h" -#include "bestatus.h" - - -int -be_function_internal_query_firmware_config(struct be_function_object *pfob, - struct BE_FIRMWARE_CONFIG *config) -{ - struct FWCMD_COMMON_FIRMWARE_CONFIG *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_FIRMWARE_CONFIG); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_FIRMWARE_CONFIG, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_FIRMWARE_CONFIG, - params.response); - rc.va = config; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, - NULL, NULL, NULL, fwcmd, &rc); -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This allocates and initializes a function object based on the information - provided by upper layer drivers. - - Returns BE_SUCCESS on success and an appropriate int on failure. - - A function object represents a single BladeEngine (logical) PCI function. - That is a function object either represents - the networking side of BladeEngine or the iSCSI side of BladeEngine. - - This routine will also detect and create an appropriate PD object for the - PCI function as needed. -*/ -int -be_function_object_create(u8 __iomem *csr_va, u8 __iomem *db_va, - u8 __iomem *pci_va, u32 function_type, - struct ring_desc *mailbox, struct be_function_object *pfob) -{ - int status; - - ASSERT(pfob); /* not a magic assert */ - ASSERT(function_type <= 2); - - TRACE(DL_INFO, "Create function object. type:%s object:0x%p", - (function_type == BE_FUNCTION_TYPE_ISCSI ? "iSCSI" : - (function_type == BE_FUNCTION_TYPE_NETWORK ? "Network" : - "Arm")), pfob); - - memset(pfob, 0, sizeof(*pfob)); - - pfob->type = function_type; - pfob->csr_va = csr_va; - pfob->db_va = db_va; - pfob->pci_va = pci_va; - - spin_lock_init(&pfob->cq_lock); - spin_lock_init(&pfob->post_lock); - spin_lock_init(&pfob->mcc_context_lock); - - - pfob->pci_function_number = 1; - - - pfob->emulate = false; - TRACE(DL_NOTE, "Non-emulation mode"); - status = be_drive_POST(pfob); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "BladeEngine POST failed."); - goto error; - } - - /* Initialize the mailbox */ - status = be_mpu_init_mailbox(pfob, mailbox); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "Failed to initialize mailbox."); - goto error; - } - /* - * Cache the firmware config for ASSERTs in hwclib and later - * driver queries. - */ - status = be_function_internal_query_firmware_config(pfob, - &pfob->fw_config); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "Failed to query firmware config."); - goto error; - } - -error: - if (status != BE_SUCCESS) { - /* No cleanup necessary */ - TRACE(DL_ERR, "Failed to create function."); - memset(pfob, 0, sizeof(*pfob)); - } - return status; -} - -/* - This routine drops the reference count on a given function object. Once - the reference count falls to zero, the function object is destroyed and all - resources held are freed. - - FunctionObject - The function object to drop the reference to. -*/ -int be_function_object_destroy(struct be_function_object *pfob) -{ - TRACE(DL_INFO, "Destroy pfob. Object:0x%p", - pfob); - - - ASSERT(pfob->mcc == NULL); - - return BE_SUCCESS; -} - -int be_function_cleanup(struct be_function_object *pfob) -{ - int status = 0; - u32 isr; - u32 host_intr; - struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl; - - - if (pfob->type == BE_FUNCTION_TYPE_NETWORK) { - status = be_rxf_multicast_config(pfob, false, 0, - NULL, NULL, NULL, NULL); - ASSERT(status == BE_SUCCESS); - } - /* VLAN */ - status = be_rxf_vlan_config(pfob, false, 0, NULL, NULL, NULL, NULL); - ASSERT(status == BE_SUCCESS); - /* - * MCC Queue -- Switches to mailbox mode. May want to destroy - * all but the MCC CQ before this call if polling CQ is much better - * performance than polling mailbox register. - */ - if (pfob->mcc) - status = be_mcc_ring_destroy(pfob->mcc); - /* - * If interrupts are disabled, clear any CEV interrupt assertions that - * fired after we stopped processing EQs. - */ - ctrl.dw[0] = PCICFG1_READ(pfob, host_timer_int_ctrl); - host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw); - if (!host_intr) - if (pfob->type == BE_FUNCTION_TYPE_NETWORK) - isr = CSR_READ(pfob, cev.isr1); - else - isr = CSR_READ(pfob, cev.isr0); - else - /* This should never happen... */ - TRACE(DL_ERR, "function_cleanup called with interrupt enabled"); - /* Function object destroy */ - status = be_function_object_destroy(pfob); - ASSERT(status == BE_SUCCESS); - - return status; -} - - -void * -be_function_prepare_embedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, u32 payld_len, u32 request_length, - u32 response_length, u32 opcode, u32 subsystem) -{ - struct FWCMD_REQUEST_HEADER *header = NULL; - u32 n; - - ASSERT(wrb); - - n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - AMAP_SET_BITS_PTR(MCC_WRB, embedded, wrb, 1); - AMAP_SET_BITS_PTR(MCC_WRB, payload_length, wrb, min(payld_len, n)); - header = (struct FWCMD_REQUEST_HEADER *)((u8 *)wrb + n); - - header->timeout = 0; - header->domain = 0; - header->request_length = max(request_length, response_length); - header->opcode = opcode; - header->subsystem = subsystem; - - return header; -} - -void * -be_function_prepare_nonembedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - void *fwcmd_va, u64 fwcmd_pa, - u32 payld_len, - u32 request_length, - u32 response_length, - u32 opcode, u32 subsystem) -{ - struct FWCMD_REQUEST_HEADER *header = NULL; - u32 n; - struct MCC_WRB_PAYLOAD_AMAP *plp; - - ASSERT(wrb); - ASSERT(fwcmd_va); - - header = (struct FWCMD_REQUEST_HEADER *) fwcmd_va; - - AMAP_SET_BITS_PTR(MCC_WRB, embedded, wrb, 0); - AMAP_SET_BITS_PTR(MCC_WRB, payload_length, wrb, payld_len); - - /* - * Assume one fragment. The caller may override the SGL by - * rewriting the 0th length and adding more entries. They - * will also need to update the sge_count. - */ - AMAP_SET_BITS_PTR(MCC_WRB, sge_count, wrb, 1); - - n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - plp = (struct MCC_WRB_PAYLOAD_AMAP *)((u8 *)wrb + n); - AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].length, plp, payld_len); - AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].pa_lo, plp, (u32)fwcmd_pa); - AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].pa_hi, plp, - upper_32_bits(fwcmd_pa)); - - header->timeout = 0; - header->domain = 0; - header->request_length = max(request_length, response_length); - header->opcode = opcode; - header->subsystem = subsystem; - - return header; -} - -struct MCC_WRB_AMAP * -be_function_peek_mcc_wrb(struct be_function_object *pfob) -{ - struct MCC_WRB_AMAP *wrb = NULL; - u32 offset; - - if (pfob->mcc) - wrb = _be_mpu_peek_ring_wrb(pfob->mcc, false); - else { - offset = offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8; - wrb = (struct MCC_WRB_AMAP *) ((u8 *) pfob->mailbox.va + - offset); - } - - if (wrb) - memset(wrb, 0, sizeof(struct MCC_WRB_AMAP)); - - return wrb; -} - -#if defined(BE_DEBUG) -void be_function_debug_print_wrb(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, void *optional_fwcmd_va, - struct be_mcc_wrb_context *wrb_context) -{ - - struct FWCMD_REQUEST_HEADER *header = NULL; - u8 embedded; - u32 n; - - embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, wrb); - - if (embedded) { - n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - header = (struct FWCMD_REQUEST_HEADER *)((u8 *)wrb + n); - } else { - header = (struct FWCMD_REQUEST_HEADER *) optional_fwcmd_va; - } - - /* Save the completed count before posting for a debug assert. */ - - if (header) { - wrb_context->opcode = header->opcode; - wrb_context->subsystem = header->subsystem; - - } else { - wrb_context->opcode = 0; - wrb_context->subsystem = 0; - } -} -#else -#define be_function_debug_print_wrb(a_, b_, c_, d_) -#endif - -int -be_function_post_mcc_wrb(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - struct be_generic_q_ctxt *q_ctxt, - mcc_wrb_cqe_callback cb, void *cb_context, - mcc_wrb_cqe_callback internal_cb, - void *internal_cb_context, void *optional_fwcmd_va, - struct be_mcc_wrb_response_copy *rc) -{ - int status; - struct be_mcc_wrb_context *wrb_context = NULL; - u64 *p; - - if (q_ctxt) { - /* Initialize context. */ - q_ctxt->context.internal_cb = internal_cb; - q_ctxt->context.internal_cb_context = internal_cb_context; - q_ctxt->context.cb = cb; - q_ctxt->context.cb_context = cb_context; - if (rc) { - q_ctxt->context.copy.length = rc->length; - q_ctxt->context.copy.fwcmd_offset = rc->fwcmd_offset; - q_ctxt->context.copy.va = rc->va; - } else - q_ctxt->context.copy.length = 0; - - q_ctxt->context.optional_fwcmd_va = optional_fwcmd_va; - - /* Queue this request */ - status = be_function_queue_mcc_wrb(pfob, q_ctxt); - - goto Error; - } - /* - * Allocate a WRB context struct to hold the callback pointers, - * status, etc. This is required if commands complete out of order. - */ - wrb_context = _be_mcc_allocate_wrb_context(pfob); - if (!wrb_context) { - TRACE(DL_WARN, "Failed to allocate MCC WRB context."); - status = BE_STATUS_SYSTEM_RESOURCES; - goto Error; - } - /* Initialize context. */ - memset(wrb_context, 0, sizeof(*wrb_context)); - wrb_context->internal_cb = internal_cb; - wrb_context->internal_cb_context = internal_cb_context; - wrb_context->cb = cb; - wrb_context->cb_context = cb_context; - if (rc) { - wrb_context->copy.length = rc->length; - wrb_context->copy.fwcmd_offset = rc->fwcmd_offset; - wrb_context->copy.va = rc->va; - } else - wrb_context->copy.length = 0; - wrb_context->wrb = wrb; - - /* - * Copy the context pointer into the WRB opaque tag field. - * Verify assumption of 64-bit tag with a compile time assert. - */ - p = (u64 *) ((u8 *)wrb + offsetof(struct BE_MCC_WRB_AMAP, tag)/8); - *p = (u64)(size_t)wrb_context; - - /* Print info about this FWCMD for debug builds. */ - be_function_debug_print_wrb(pfob, wrb, optional_fwcmd_va, wrb_context); - - /* - * issue the WRB to the MPU as appropriate - */ - if (pfob->mcc) { - /* - * we're in WRB mode, pass to the mcc layer - */ - status = _be_mpu_post_wrb_ring(pfob->mcc, wrb, wrb_context); - } else { - /* - * we're in mailbox mode - */ - status = _be_mpu_post_wrb_mailbox(pfob, wrb, wrb_context); - - /* mailbox mode always completes synchronously */ - ASSERT(status != BE_STATUS_PENDING); - } - -Error: - - return status; -} - -int -be_function_ring_destroy(struct be_function_object *pfob, - u32 id, u32 ring_type, mcc_wrb_cqe_callback cb, - void *cb_context, mcc_wrb_cqe_callback internal_cb, - void *internal_cb_context) -{ - - struct FWCMD_COMMON_RING_DESTROY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - TRACE(DL_INFO, "Destroy ring id:%d type:%d", id, ring_type); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in destroy ring."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_RING_DESTROY); - - fwcmd->params.request.id = id; - fwcmd->params.request.ring_type = ring_type; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, cb_context, - internal_cb, internal_cb_context, fwcmd, NULL); - if (status != BE_SUCCESS && status != BE_PENDING) { - TRACE(DL_ERR, "Ring destroy fwcmd failed. id:%d ring_type:%d", - id, ring_type); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -void -be_rd_to_pa_list(struct ring_desc *rd, struct PHYS_ADDR *pa_list, u32 max_num) -{ - u32 num_pages = PAGES_SPANNED(rd->va, rd->length); - u32 i = 0; - u64 pa = rd->pa; - __le64 lepa; - - ASSERT(pa_list); - ASSERT(pa); - - for (i = 0; i < min(num_pages, max_num); i++) { - lepa = cpu_to_le64(pa); - pa_list[i].lo = (u32)lepa; - pa_list[i].hi = upper_32_bits(lepa); - pa += PAGE_SIZE; - } -} - - - -/*----------------------------------------------------------------------------- - * Function: be_function_get_fw_version - * Retrieves the firmware version on the adpater. If the callback is - * NULL this call executes synchronously. If the callback is not NULL, - * the returned status will be BE_PENDING if the command was issued - * successfully. - * pfob - - * fwv - Pointer to response buffer if callback is NULL. - * cb - Callback function invoked when the FWCMD completes. - * cb_context - Passed to the callback function. - * return pend_status - BE_SUCCESS (0) on success. - * BE_PENDING (postive value) if the FWCMD - * completion is pending. Negative error code on failure. - *--------------------------------------------------------------------------- - */ -int -be_function_get_fw_version(struct be_function_object *pfob, - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD *fwv, - mcc_wrb_cqe_callback cb, void *cb_context) -{ - int status = BE_SUCCESS; - struct MCC_WRB_AMAP *wrb = NULL; - struct FWCMD_COMMON_GET_FW_VERSION *fwcmd = NULL; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - - if (!cb && !fwv) { - TRACE(DL_ERR, "callback and response buffer NULL!"); - status = BE_NOT_OK; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_FW_VERSION); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_GET_FW_VERSION, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_GET_FW_VERSION, - params.response); - rc.va = fwv; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, - cb_context, NULL, NULL, fwcmd, &rc); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -int -be_function_queue_mcc_wrb(struct be_function_object *pfob, - struct be_generic_q_ctxt *q_ctxt) -{ - int status; - - ASSERT(q_ctxt); - - /* - * issue the WRB to the MPU as appropriate - */ - if (pfob->mcc) { - - /* We're in ring mode. Queue this item. */ - pfob->mcc->backlog_length++; - list_add_tail(&q_ctxt->context.list, &pfob->mcc->backlog); - status = BE_PENDING; - } else { - status = BE_NOT_OK; - } - return status; -} - diff --git a/drivers/staging/benet/fwcmd_common.h b/drivers/staging/benet/fwcmd_common.h deleted file mode 100644 index 406e0d6fa985..000000000000 --- a/drivers/staging/benet/fwcmd_common.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_common_amap_h__ -#define __fwcmd_common_amap_h__ -#include "host_struct.h" - -/* --- PHY_LINK_DUPLEX_ENUM --- */ -#define PHY_LINK_DUPLEX_NONE (0) -#define PHY_LINK_DUPLEX_HALF (1) -#define PHY_LINK_DUPLEX_FULL (2) - -/* --- PHY_LINK_SPEED_ENUM --- */ -#define PHY_LINK_SPEED_ZERO (0) /* No link. */ -#define PHY_LINK_SPEED_10MBPS (1) /* 10 Mbps */ -#define PHY_LINK_SPEED_100MBPS (2) /* 100 Mbps */ -#define PHY_LINK_SPEED_1GBPS (3) /* 1 Gbps */ -#define PHY_LINK_SPEED_10GBPS (4) /* 10 Gbps */ - -/* --- PHY_LINK_FAULT_ENUM --- */ -#define PHY_LINK_FAULT_NONE (0) /* No fault status - available or detected */ -#define PHY_LINK_FAULT_LOCAL (1) /* Local fault detected */ -#define PHY_LINK_FAULT_REMOTE (2) /* Remote fault detected */ - -/* --- BE_ULP_MASK --- */ -#define BE_ULP0_MASK (1) -#define BE_ULP1_MASK (2) -#define BE_ULP2_MASK (4) - -/* --- NTWK_ACTIVE_PORT --- */ -#define NTWK_PORT_A (0) /* Port A is currently active */ -#define NTWK_PORT_B (1) /* Port B is currently active */ -#define NTWK_NO_ACTIVE_PORT (15) /* Both ports have lost link */ - -/* --- NTWK_LINK_TYPE --- */ -#define NTWK_LINK_TYPE_PHYSICAL (0) /* link up/down event - applies to BladeEngine's - Physical Ports - */ -#define NTWK_LINK_TYPE_VIRTUAL (1) /* Virtual link up/down event - reported by BladeExchange. - This applies only when the - VLD feature is enabled - */ - -/* - * --- FWCMD_MAC_TYPE_ENUM --- - * This enum defines the types of MAC addresses in the RXF MAC Address Table. - */ -#define MAC_ADDRESS_TYPE_STORAGE (0) /* Storage MAC Address */ -#define MAC_ADDRESS_TYPE_NETWORK (1) /* Network MAC Address */ -#define MAC_ADDRESS_TYPE_PD (2) /* Protection Domain MAC Addr */ -#define MAC_ADDRESS_TYPE_MANAGEMENT (3) /* Managment MAC Address */ - - -/* --- FWCMD_RING_TYPE_ENUM --- */ -#define FWCMD_RING_TYPE_ETH_RX (1) /* Ring created with */ - /* FWCMD_COMMON_ETH_RX_CREATE. */ -#define FWCMD_RING_TYPE_ETH_TX (2) /* Ring created with */ - /* FWCMD_COMMON_ETH_TX_CREATE. */ -#define FWCMD_RING_TYPE_ISCSI_WRBQ (3) /* Ring created with */ - /* FWCMD_COMMON_ISCSI_WRBQ_CREATE. */ -#define FWCMD_RING_TYPE_ISCSI_DEFQ (4) /* Ring created with */ - /* FWCMD_COMMON_ISCSI_DEFQ_CREATE. */ -#define FWCMD_RING_TYPE_TPM_WRBQ (5) /* Ring created with */ - /* FWCMD_COMMON_TPM_WRBQ_CREATE. */ -#define FWCMD_RING_TYPE_TPM_DEFQ (6) /* Ring created with */ - /* FWCMD_COMMONTPM_TDEFQ_CREATE. */ -#define FWCMD_RING_TYPE_TPM_RQ (7) /* Ring created with */ - /* FWCMD_COMMON_TPM_RQ_CREATE. */ -#define FWCMD_RING_TYPE_MCC (8) /* Ring created with */ - /* FWCMD_COMMON_MCC_CREATE. */ -#define FWCMD_RING_TYPE_CQ (9) /* Ring created with */ - /* FWCMD_COMMON_CQ_CREATE. */ -#define FWCMD_RING_TYPE_EQ (10) /* Ring created with */ - /* FWCMD_COMMON_EQ_CREATE. */ -#define FWCMD_RING_TYPE_QP (11) /* Ring created with */ - /* FWCMD_RDMA_QP_CREATE. */ - - -/* --- ETH_TX_RING_TYPE_ENUM --- */ -#define ETH_TX_RING_TYPE_FORWARDING (1) /* Ethernet ring for - forwarding packets */ -#define ETH_TX_RING_TYPE_STANDARD (2) /* Ethernet ring for sending - network packets. */ -#define ETH_TX_RING_TYPE_BOUND (3) /* Ethernet ring bound to the - port specified in the command - header.port_number field. - Rings of this type are - NOT subject to the - failover logic implemented - in the BladeEngine. - */ - -/* --- FWCMD_COMMON_QOS_TYPE_ENUM --- */ -#define QOS_BITS_NIC (1) /* max_bits_per_second_NIC */ - /* field is valid. */ -#define QOS_PKTS_NIC (2) /* max_packets_per_second_NIC */ - /* field is valid. */ -#define QOS_IOPS_ISCSI (4) /* max_ios_per_second_iSCSI */ - /*field is valid. */ -#define QOS_VLAN_TAG (8) /* domain_VLAN_tag field - is valid. */ -#define QOS_FABRIC_ID (16) /* fabric_domain_ID field - is valid. */ -#define QOS_OEM_PARAMS (32) /* qos_params_oem field - is valid. */ -#define QOS_TPUT_ISCSI (64) /* max_bytes_per_second_iSCSI - field is valid. */ - - -/* - * --- FAILOVER_CONFIG_ENUM --- - * Failover configuration setting used in FWCMD_COMMON_FORCE_FAILOVER - */ -#define FAILOVER_CONFIG_NO_CHANGE (0) /* No change to automatic */ - /* port failover setting. */ -#define FAILOVER_CONFIG_ON (1) /* Automatic port failover - on link down is enabled. */ -#define FAILOVER_CONFIG_OFF (2) /* Automatic port failover - on link down is disabled. */ - -/* - * --- FAILOVER_PORT_ENUM --- - * Failover port setting used in FWCMD_COMMON_FORCE_FAILOVER - */ -#define FAILOVER_PORT_A (0) /* Selects port A. */ -#define FAILOVER_PORT_B (1) /* Selects port B. */ -#define FAILOVER_PORT_NONE (15) /* No port change requested. */ - - -/* - * --- MGMT_FLASHROM_OPCODE --- - * Flash ROM operation code - */ -#define MGMT_FLASHROM_OPCODE_FLASH (1) /* Commit downloaded data - to Flash ROM */ -#define MGMT_FLASHROM_OPCODE_SAVE (2) /* Save downloaded data to - ARM's DDR - do not flash */ -#define MGMT_FLASHROM_OPCODE_CLEAR (3) /* Erase specified component - from FlashROM */ -#define MGMT_FLASHROM_OPCODE_REPORT (4) /* Read specified component - from Flash ROM */ -#define MGMT_FLASHROM_OPCODE_IMAGE_INFO (5) /* Returns size of a - component */ - -/* - * --- MGMT_FLASHROM_OPTYPE --- - * Flash ROM operation type - */ -#define MGMT_FLASHROM_OPTYPE_CODE_FIRMWARE (0) /* Includes ARM firmware, - IPSec (optional) and EP - firmware */ -#define MGMT_FLASHROM_OPTYPE_CODE_REDBOOT (1) -#define MGMT_FLASHROM_OPTYPE_CODE_BIOS (2) -#define MGMT_FLASHROM_OPTYPE_CODE_PXE_BIOS (3) -#define MGMT_FLASHROM_OPTYPE_CODE_CTRLS (4) -#define MGMT_FLASHROM_OPTYPE_CFG_IPSEC (5) -#define MGMT_FLASHROM_OPTYPE_CFG_INI (6) -#define MGMT_FLASHROM_OPTYPE_ROM_OFFSET_SPECIFIED (7) - -/* - * --- FLASHROM_TYPE --- - * Flash ROM manufacturers supported in the f/w - */ -#define INTEL (0) -#define SPANSION (1) -#define MICRON (2) - -/* --- DDR_CAS_TYPE --- */ -#define CAS_3 (0) -#define CAS_4 (1) -#define CAS_5 (2) - -/* --- DDR_SIZE_TYPE --- */ -#define SIZE_256MB (0) -#define SIZE_512MB (1) - -/* --- DDR_MODE_TYPE --- */ -#define DDR_NO_ECC (0) -#define DDR_ECC (1) - -/* --- INTERFACE_10GB_TYPE --- */ -#define CX4_TYPE (0) -#define XFP_TYPE (1) - -/* --- BE_CHIP_MAX_MTU --- */ -#define CHIP_MAX_MTU (9000) - -/* --- XAUI_STATE_ENUM --- */ -#define XAUI_STATE_ENABLE (0) /* This MUST be the default - value for all requests - which set/change - equalization parameter. */ -#define XAUI_STATE_DISABLE (255) /* The XAUI for both ports - may be disabled for EMI - tests. There is no - provision for turning off - individual ports. - */ -/* --- BE_ASIC_REVISION --- */ -#define BE_ASIC_REV_A0 (1) -#define BE_ASIC_REV_A1 (2) - -#endif /* __fwcmd_common_amap_h__ */ diff --git a/drivers/staging/benet/fwcmd_common_bmap.h b/drivers/staging/benet/fwcmd_common_bmap.h deleted file mode 100644 index a007cf276500..000000000000 --- a/drivers/staging/benet/fwcmd_common_bmap.h +++ /dev/null @@ -1,717 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_common_bmap_h__ -#define __fwcmd_common_bmap_h__ -#include "fwcmd_types_bmap.h" -#include "fwcmd_hdr_bmap.h" - -#if defined(__BIG_ENDIAN) - /* Physical Address. */ -struct PHYS_ADDR { - union { - struct { - u32 lo; /* DWORD 0 */ - u32 hi; /* DWORD 1 */ - } __packed; /* unnamed struct */ - u32 dw[2]; /* dword union */ - }; /* unnamed union */ -} __packed ; - - -#else - /* Physical Address. */ -struct PHYS_ADDR { - union { - struct { - u32 lo; /* DWORD 0 */ - u32 hi; /* DWORD 1 */ - } __packed; /* unnamed struct */ - u32 dw[2]; /* dword union */ - }; /* unnamed union */ -} __packed ; - -struct BE_LINK_STATUS { - u8 mac0_duplex; - u8 mac0_speed; - u8 mac1_duplex; - u8 mac1_speed; - u8 mgmt_mac_duplex; - u8 mgmt_mac_speed; - u8 active_port; - u8 rsvd0; - u8 mac0_fault; - u8 mac1_fault; - u16 rsvd1; -} __packed; -#endif - -struct FWCMD_COMMON_ANON_170_REQUEST { - u32 rsvd0; -} __packed; - -union LINK_STATUS_QUERY_PARAMS { - struct BE_LINK_STATUS response; - struct FWCMD_COMMON_ANON_170_REQUEST request; -} __packed; - -/* - * Queries the the link status for all ports. The valid values below - * DO NOT indicate that a particular duplex or speed is supported by - * BladeEngine. These enumerations simply list all possible duplexes - * and speeds for any port. Consult BladeEngine product documentation - * for the supported parameters. - */ -struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY { - union FWCMD_HEADER header; - union LINK_STATUS_QUERY_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_171_REQUEST { - u8 type; - u8 port; - u8 mac1; - u8 permanent; -} __packed; - -struct FWCMD_COMMON_ANON_172_RESPONSE { - struct MAC_ADDRESS_FORMAT mac; -} __packed; - -union NTWK_MAC_QUERY_PARAMS { - struct FWCMD_COMMON_ANON_171_REQUEST request; - struct FWCMD_COMMON_ANON_172_RESPONSE response; -} __packed; - -/* Queries one MAC address. */ -struct FWCMD_COMMON_NTWK_MAC_QUERY { - union FWCMD_HEADER header; - union NTWK_MAC_QUERY_PARAMS params; -} __packed; - -struct MAC_SET_PARAMS_IN { - u8 type; - u8 port; - u8 mac1; - u8 invalidate; - struct MAC_ADDRESS_FORMAT mac; -} __packed; - -struct MAC_SET_PARAMS_OUT { - u32 rsvd0; -} __packed; - -union MAC_SET_PARAMS { - struct MAC_SET_PARAMS_IN request; - struct MAC_SET_PARAMS_OUT response; -} __packed; - -/* Sets a MAC address. */ -struct FWCMD_COMMON_NTWK_MAC_SET { - union FWCMD_HEADER header; - union MAC_SET_PARAMS params; -} __packed; - -/* MAC address list. */ -struct NTWK_MULTICAST_MAC_LIST { - u8 byte[6]; -} __packed; - -struct FWCMD_COMMON_NTWK_MULTICAST_SET_REQUEST_PAYLOAD { - u16 num_mac; - u8 promiscuous; - u8 rsvd0; - struct NTWK_MULTICAST_MAC_LIST mac[32]; -} __packed; - -struct FWCMD_COMMON_ANON_174_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_173_PARAMS { - struct FWCMD_COMMON_NTWK_MULTICAST_SET_REQUEST_PAYLOAD request; - struct FWCMD_COMMON_ANON_174_RESPONSE response; -} __packed; - -/* - * Sets multicast address hash. The MPU will merge the MAC address lists - * from all clients, including the networking and storage functions. - * This command may fail if the final merged list of MAC addresses exceeds - * 32 entries. - */ -struct FWCMD_COMMON_NTWK_MULTICAST_SET { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_173_PARAMS params; -} __packed; - -struct FWCMD_COMMON_NTWK_VLAN_CONFIG_REQUEST_PAYLOAD { - u16 num_vlan; - u8 promiscuous; - u8 rsvd0; - u16 vlan_tag[32]; -} __packed; - -struct FWCMD_COMMON_ANON_176_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_175_PARAMS { - struct FWCMD_COMMON_NTWK_VLAN_CONFIG_REQUEST_PAYLOAD request; - struct FWCMD_COMMON_ANON_176_RESPONSE response; -} __packed; - -/* - * Sets VLAN tag filter. The MPU will merge the VLAN tag list from all - * clients, including the networking and storage functions. This command - * may fail if the final vlan_tag array (from all functions) is longer - * than 32 entries. - */ -struct FWCMD_COMMON_NTWK_VLAN_CONFIG { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_175_PARAMS params; -} __packed; - -struct RING_DESTROY_REQUEST { - u16 ring_type; - u16 id; - u8 bypass_flush; - u8 rsvd0; - u16 rsvd1; -} __packed; - -struct FWCMD_COMMON_ANON_190_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_189_PARAMS { - struct RING_DESTROY_REQUEST request; - struct FWCMD_COMMON_ANON_190_RESPONSE response; -} __packed; -/* - * Command for destroying any ring. The connection(s) using the ring should - * be quiesced before destroying the ring. - */ -struct FWCMD_COMMON_RING_DESTROY { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_189_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_192_REQUEST { - u16 num_pages; - u16 rsvd0; - struct CQ_CONTEXT_AMAP context; - struct PHYS_ADDR pages[4]; -} __packed ; - -struct FWCMD_COMMON_ANON_193_RESPONSE { - u16 cq_id; -} __packed ; - -union FWCMD_COMMON_ANON_191_PARAMS { - struct FWCMD_COMMON_ANON_192_REQUEST request; - struct FWCMD_COMMON_ANON_193_RESPONSE response; -} __packed ; - -/* - * Command for creating a completion queue. A Completion Queue must span - * at least 1 page and at most 4 pages. Each completion queue entry - * is 16 bytes regardless of CQ entry format. Thus the ring must be - * at least 256 entries deep (corresponding to 1 page) and can be at - * most 1024 entries deep (corresponding to 4 pages). The number of - * pages posted must contain the CQ ring size as encoded in the context. - * - */ -struct FWCMD_COMMON_CQ_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_191_PARAMS params; -} __packed ; - -struct FWCMD_COMMON_ANON_198_REQUEST { - u16 num_pages; - u16 rsvd0; - struct EQ_CONTEXT_AMAP context; - struct PHYS_ADDR pages[8]; -} __packed ; - -struct FWCMD_COMMON_ANON_199_RESPONSE { - u16 eq_id; -} __packed ; - -union FWCMD_COMMON_ANON_197_PARAMS { - struct FWCMD_COMMON_ANON_198_REQUEST request; - struct FWCMD_COMMON_ANON_199_RESPONSE response; -} __packed ; - -/* - * Command for creating a event queue. An Event Queue must span at least - * 1 page and at most 8 pages. The number of pages posted must contain - * the EQ ring. The ring is defined by the size of the EQ entries (encoded - * in the context) and the number of EQ entries (also encoded in the - * context). - */ -struct FWCMD_COMMON_EQ_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_197_PARAMS params; -} __packed ; - -struct FWCMD_COMMON_ANON_201_REQUEST { - u16 cq_id; - u16 bcmc_cq_id; - u16 num_pages; - u16 rsvd0; - struct PHYS_ADDR pages[2]; -} __packed; - -struct FWCMD_COMMON_ANON_202_RESPONSE { - u16 id; -} __packed; - -union FWCMD_COMMON_ANON_200_PARAMS { - struct FWCMD_COMMON_ANON_201_REQUEST request; - struct FWCMD_COMMON_ANON_202_RESPONSE response; -} __packed; - -/* - * Command for creating Ethernet receive ring. An ERX ring contains ETH_RX_D - * entries (8 bytes each). An ERX ring must be 1024 entries deep - * (corresponding to 2 pages). - */ -struct FWCMD_COMMON_ETH_RX_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_200_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_204_REQUEST { - u16 num_pages; - u8 ulp_num; - u8 type; - struct ETX_CONTEXT_AMAP context; - struct PHYS_ADDR pages[8]; -} __packed ; - -struct FWCMD_COMMON_ANON_205_RESPONSE { - u16 cid; - u8 ulp_num; - u8 rsvd0; -} __packed ; - -union FWCMD_COMMON_ANON_203_PARAMS { - struct FWCMD_COMMON_ANON_204_REQUEST request; - struct FWCMD_COMMON_ANON_205_RESPONSE response; -} __packed ; - -/* - * Command for creating an Ethernet transmit ring. An ETX ring contains - * ETH_WRB entries (16 bytes each). An ETX ring must be at least 256 - * entries deep (corresponding to 1 page) and at most 2k entries deep - * (corresponding to 8 pages). - */ -struct FWCMD_COMMON_ETH_TX_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_203_PARAMS params; -} __packed ; - -struct FWCMD_COMMON_ANON_222_REQUEST { - u16 num_pages; - u16 rsvd0; - struct MCC_RING_CONTEXT_AMAP context; - struct PHYS_ADDR pages[8]; -} __packed ; - -struct FWCMD_COMMON_ANON_223_RESPONSE { - u16 id; -} __packed ; - -union FWCMD_COMMON_ANON_221_PARAMS { - struct FWCMD_COMMON_ANON_222_REQUEST request; - struct FWCMD_COMMON_ANON_223_RESPONSE response; -} __packed ; - -/* - * Command for creating the MCC ring. An MCC ring must be at least 16 - * entries deep (corresponding to 1 page) and at most 128 entries deep - * (corresponding to 8 pages). - */ -struct FWCMD_COMMON_MCC_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_221_PARAMS params; -} __packed ; - -struct GET_QOS_IN { - u32 qos_params_rsvd; -} __packed; - -struct GET_QOS_OUT { - u32 max_bits_per_second_NIC; - u32 max_packets_per_second_NIC; - u32 max_ios_per_second_iSCSI; - u32 max_bytes_per_second_iSCSI; - u16 domain_VLAN_tag; - u16 fabric_domain_ID; - u32 qos_params_oem[4]; -} __packed; - -union GET_QOS_PARAMS { - struct GET_QOS_IN request; - struct GET_QOS_OUT response; -} __packed; - -/* QOS/Bandwidth settings per domain. Applicable only in VMs. */ -struct FWCMD_COMMON_GET_QOS { - union FWCMD_HEADER header; - union GET_QOS_PARAMS params; -} __packed; - -struct SET_QOS_IN { - u32 valid_flags; - u32 max_bits_per_second_NIC; - u32 max_packets_per_second_NIC; - u32 max_ios_per_second_iSCSI; - u32 max_bytes_per_second_iSCSI; - u16 domain_VLAN_tag; - u16 fabric_domain_ID; - u32 qos_params_oem[4]; -} __packed; - -struct SET_QOS_OUT { - u32 qos_params_rsvd; -} __packed; - -union SET_QOS_PARAMS { - struct SET_QOS_IN request; - struct SET_QOS_OUT response; -} __packed; - -/* QOS/Bandwidth settings per domain. Applicable only in VMs. */ -struct FWCMD_COMMON_SET_QOS { - union FWCMD_HEADER header; - union SET_QOS_PARAMS params; -} __packed; - -struct SET_FRAME_SIZE_IN { - u32 max_tx_frame_size; - u32 max_rx_frame_size; -} __packed; - -struct SET_FRAME_SIZE_OUT { - u32 chip_max_tx_frame_size; - u32 chip_max_rx_frame_size; -} __packed; - -union SET_FRAME_SIZE_PARAMS { - struct SET_FRAME_SIZE_IN request; - struct SET_FRAME_SIZE_OUT response; -} __packed; - -/* Set frame size command. Only host domain may issue this command. */ -struct FWCMD_COMMON_SET_FRAME_SIZE { - union FWCMD_HEADER header; - union SET_FRAME_SIZE_PARAMS params; -} __packed; - -struct FORCE_FAILOVER_IN { - u32 move_to_port; - u32 failover_config; -} __packed; - -struct FWCMD_COMMON_ANON_231_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_230_PARAMS { - struct FORCE_FAILOVER_IN request; - struct FWCMD_COMMON_ANON_231_RESPONSE response; -} __packed; - -/* - * Use this command to control failover in BladeEngine. It may be used - * to failback to a restored port or to forcibly move traffic from - * one port to another. It may also be used to enable or disable the - * automatic failover feature. This command can only be issued by domain - * 0. - */ -struct FWCMD_COMMON_FORCE_FAILOVER { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_230_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_240_REQUEST { - u64 context; -} __packed; - -struct FWCMD_COMMON_ANON_241_RESPONSE { - u64 context; -} __packed; - -union FWCMD_COMMON_ANON_239_PARAMS { - struct FWCMD_COMMON_ANON_240_REQUEST request; - struct FWCMD_COMMON_ANON_241_RESPONSE response; -} __packed; - -/* - * This command can be used by clients as a no-operation request. Typical - * uses for drivers are as a heartbeat mechanism, or deferred processing - * catalyst. The ARM will always complete this command with a good completion. - * The 64-bit parameter is not touched by the ARM processor. - */ -struct FWCMD_COMMON_NOP { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_239_PARAMS params; -} __packed; - -struct NTWK_RX_FILTER_SETTINGS { - u8 promiscuous; - u8 ip_cksum; - u8 tcp_cksum; - u8 udp_cksum; - u8 pass_err; - u8 pass_ckerr; - u8 strip_crc; - u8 mcast_en; - u8 bcast_en; - u8 mcast_promiscuous_en; - u8 unicast_en; - u8 vlan_promiscuous; -} __packed; - -union FWCMD_COMMON_ANON_242_PARAMS { - struct NTWK_RX_FILTER_SETTINGS request; - struct NTWK_RX_FILTER_SETTINGS response; -} __packed; - -/* - * This command is used to modify the ethernet receive filter configuration. - * Only domain 0 network function drivers may issue this command. The - * applied configuration is returned in the response payload. Note: - * Some receive packet filter settings are global on BladeEngine and - * can affect both the storage and network function clients that the - * BladeEngine hardware and firmware serve. Additionaly, depending - * on the revision of BladeEngine, some ethernet receive filter settings - * are dependent on others. If a dependency exists between settings - * for the BladeEngine revision, and the command request settings do - * not meet the dependency requirement, the invalid settings will not - * be applied despite the comand succeeding. For example: a driver may - * request to enable broadcast packets, but not enable multicast packets. - * On early revisions of BladeEngine, there may be no distinction between - * broadcast and multicast filters, so broadcast could not be enabled - * without enabling multicast. In this scenario, the comand would still - * succeed, but the response payload would indicate the previously - * configured broadcast and multicast setting. - */ -struct FWCMD_COMMON_NTWK_RX_FILTER { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_242_PARAMS params; -} __packed; - - -struct FWCMD_COMMON_ANON_244_REQUEST { - u32 rsvd0; -} __packed; - -struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD { - u8 firmware_version_string[32]; - u8 fw_on_flash_version_string[32]; -} __packed; - -union FWCMD_COMMON_ANON_243_PARAMS { - struct FWCMD_COMMON_ANON_244_REQUEST request; - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD response; -} __packed; - -/* This comand retrieves the firmware version. */ -struct FWCMD_COMMON_GET_FW_VERSION { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_243_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_246_REQUEST { - u16 tx_flow_control; - u16 rx_flow_control; -} __packed; - -struct FWCMD_COMMON_ANON_247_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_245_PARAMS { - struct FWCMD_COMMON_ANON_246_REQUEST request; - struct FWCMD_COMMON_ANON_247_RESPONSE response; -} __packed; - -/* - * This comand is used to program BladeEngine flow control behavior. - * Only the host networking driver is allowed to use this comand. - */ -struct FWCMD_COMMON_SET_FLOW_CONTROL { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_245_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_249_REQUEST { - u32 rsvd0; -} __packed; - -struct FWCMD_COMMON_ANON_250_RESPONSE { - u16 tx_flow_control; - u16 rx_flow_control; -} __packed; - -union FWCMD_COMMON_ANON_248_PARAMS { - struct FWCMD_COMMON_ANON_249_REQUEST request; - struct FWCMD_COMMON_ANON_250_RESPONSE response; -} __packed; - -/* This comand is used to read BladeEngine flow control settings. */ -struct FWCMD_COMMON_GET_FLOW_CONTROL { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_248_PARAMS params; -} __packed; - -struct EQ_DELAY_PARAMS { - u32 eq_id; - u32 delay_in_microseconds; -} __packed; - -struct FWCMD_COMMON_ANON_257_REQUEST { - u32 num_eq; - u32 rsvd0; - struct EQ_DELAY_PARAMS delay[16]; -} __packed; - -struct FWCMD_COMMON_ANON_258_RESPONSE { - u32 delay_resolution_in_microseconds; - u32 delay_max_in_microseconds; -} __packed; - -union MODIFY_EQ_DELAY_PARAMS { - struct FWCMD_COMMON_ANON_257_REQUEST request; - struct FWCMD_COMMON_ANON_258_RESPONSE response; -} __packed; - -/* This comand changes the EQ delay for a given set of EQs. */ -struct FWCMD_COMMON_MODIFY_EQ_DELAY { - union FWCMD_HEADER header; - union MODIFY_EQ_DELAY_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_260_REQUEST { - u32 rsvd0; -} __packed; - -struct BE_FIRMWARE_CONFIG { - u16 be_config_number; - u16 asic_revision; - u32 nic_ulp_mask; - u32 tulp_mask; - u32 iscsi_ulp_mask; - u32 rdma_ulp_mask; - u32 rsvd0[4]; - u32 eth_tx_id_start; - u32 eth_tx_id_count; - u32 eth_rx_id_start; - u32 eth_rx_id_count; - u32 tpm_wrbq_id_start; - u32 tpm_wrbq_id_count; - u32 tpm_defq_id_start; - u32 tpm_defq_id_count; - u32 iscsi_wrbq_id_start; - u32 iscsi_wrbq_id_count; - u32 iscsi_defq_id_start; - u32 iscsi_defq_id_count; - u32 rdma_qp_id_start; - u32 rdma_qp_id_count; - u32 rsvd1[8]; -} __packed; - -union FWCMD_COMMON_ANON_259_PARAMS { - struct FWCMD_COMMON_ANON_260_REQUEST request; - struct BE_FIRMWARE_CONFIG response; -} __packed; - -/* - * This comand queries the current firmware configuration parameters. - * The static configuration type is defined by be_config_number. This - * differentiates different BladeEngine builds, such as iSCSI Initiator - * versus iSCSI Target. For a given static configuration, the Upper - * Layer Protocol (ULP) processors may be reconfigured to support different - * protocols. Each ULP processor supports one or more protocols. The - * masks indicate which processors are configured for each protocol. - * For a given static configuration, the number of TCP connections - * supported for each protocol may vary. The *_id_start and *_id_count - * variables define a linear range of IDs that are available for each - * supported protocol. The *_id_count may be used by the driver to allocate - * the appropriate number of connection resources. The *_id_start may - * be used to map the arbitrary range of IDs to a zero-based range - * of indices. - */ -struct FWCMD_COMMON_FIRMWARE_CONFIG { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_259_PARAMS params; -} __packed; - -struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS { - u32 emph_lev_sel_port0; - u32 emph_lev_sel_port1; - u8 xaui_vo_sel; - u8 xaui_state; - u16 rsvd0; - u32 xaui_eq_vector; -} __packed; - -struct FWCMD_COMMON_ANON_262_REQUEST { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_261_PARAMS { - struct FWCMD_COMMON_ANON_262_REQUEST request; - struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS response; -} __packed; - -/* - * This comand can be used to read XAUI equalization parameters. The - * ARM firmware applies default equalization parameters during initialization. - * These parameters may be customer-specific when derived from the - * SEEPROM. See SEEPROM_DATA for equalization specific fields. - */ -struct FWCMD_COMMON_GET_PORT_EQUALIZATION { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_261_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_264_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_263_PARAMS { - struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS request; - struct FWCMD_COMMON_ANON_264_RESPONSE response; -} __packed; - -/* - * This comand can be used to set XAUI equalization parameters. The ARM - * firmware applies default equalization parameters during initialization. - * These parameters may be customer-specific when derived from the - * SEEPROM. See SEEPROM_DATA for equalization specific fields. - */ -struct FWCMD_COMMON_SET_PORT_EQUALIZATION { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_263_PARAMS params; -} __packed; - -#endif /* __fwcmd_common_bmap_h__ */ diff --git a/drivers/staging/benet/fwcmd_eth_bmap.h b/drivers/staging/benet/fwcmd_eth_bmap.h deleted file mode 100644 index 234b179eace6..000000000000 --- a/drivers/staging/benet/fwcmd_eth_bmap.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_eth_bmap_h__ -#define __fwcmd_eth_bmap_h__ -#include "fwcmd_hdr_bmap.h" -#include "fwcmd_types_bmap.h" - -struct MIB_ETH_STATISTICS_PARAMS_IN { - u32 rsvd0; -} __packed; - -struct BE_RXF_STATS { - u32 p0recvdtotalbytesLSD; /* DWORD 0 */ - u32 p0recvdtotalbytesMSD; /* DWORD 1 */ - u32 p0recvdtotalframes; /* DWORD 2 */ - u32 p0recvdunicastframes; /* DWORD 3 */ - u32 p0recvdmulticastframes; /* DWORD 4 */ - u32 p0recvdbroadcastframes; /* DWORD 5 */ - u32 p0crcerrors; /* DWORD 6 */ - u32 p0alignmentsymerrs; /* DWORD 7 */ - u32 p0pauseframesrecvd; /* DWORD 8 */ - u32 p0controlframesrecvd; /* DWORD 9 */ - u32 p0inrangelenerrors; /* DWORD 10 */ - u32 p0outrangeerrors; /* DWORD 11 */ - u32 p0frametoolongerrors; /* DWORD 12 */ - u32 p0droppedaddressmatch; /* DWORD 13 */ - u32 p0droppedvlanmismatch; /* DWORD 14 */ - u32 p0ipdroppedtoosmall; /* DWORD 15 */ - u32 p0ipdroppedtooshort; /* DWORD 16 */ - u32 p0ipdroppedhdrtoosmall; /* DWORD 17 */ - u32 p0tcpdroppedlen; /* DWORD 18 */ - u32 p0droppedrunt; /* DWORD 19 */ - u32 p0recvd64; /* DWORD 20 */ - u32 p0recvd65_127; /* DWORD 21 */ - u32 p0recvd128_256; /* DWORD 22 */ - u32 p0recvd256_511; /* DWORD 23 */ - u32 p0recvd512_1023; /* DWORD 24 */ - u32 p0recvd1518_1522; /* DWORD 25 */ - u32 p0recvd1522_2047; /* DWORD 26 */ - u32 p0recvd2048_4095; /* DWORD 27 */ - u32 p0recvd4096_8191; /* DWORD 28 */ - u32 p0recvd8192_9216; /* DWORD 29 */ - u32 p0rcvdipcksmerrs; /* DWORD 30 */ - u32 p0recvdtcpcksmerrs; /* DWORD 31 */ - u32 p0recvdudpcksmerrs; /* DWORD 32 */ - u32 p0recvdnonrsspackets; /* DWORD 33 */ - u32 p0recvdippackets; /* DWORD 34 */ - u32 p0recvdchute1packets; /* DWORD 35 */ - u32 p0recvdchute2packets; /* DWORD 36 */ - u32 p0recvdchute3packets; /* DWORD 37 */ - u32 p0recvdipsecpackets; /* DWORD 38 */ - u32 p0recvdmanagementpackets; /* DWORD 39 */ - u32 p0xmitbyteslsd; /* DWORD 40 */ - u32 p0xmitbytesmsd; /* DWORD 41 */ - u32 p0xmitunicastframes; /* DWORD 42 */ - u32 p0xmitmulticastframes; /* DWORD 43 */ - u32 p0xmitbroadcastframes; /* DWORD 44 */ - u32 p0xmitpauseframes; /* DWORD 45 */ - u32 p0xmitcontrolframes; /* DWORD 46 */ - u32 p0xmit64; /* DWORD 47 */ - u32 p0xmit65_127; /* DWORD 48 */ - u32 p0xmit128_256; /* DWORD 49 */ - u32 p0xmit256_511; /* DWORD 50 */ - u32 p0xmit512_1023; /* DWORD 51 */ - u32 p0xmit1518_1522; /* DWORD 52 */ - u32 p0xmit1522_2047; /* DWORD 53 */ - u32 p0xmit2048_4095; /* DWORD 54 */ - u32 p0xmit4096_8191; /* DWORD 55 */ - u32 p0xmit8192_9216; /* DWORD 56 */ - u32 p0rxfifooverflowdropped; /* DWORD 57 */ - u32 p0ipseclookupfaileddropped; /* DWORD 58 */ - u32 p1recvdtotalbytesLSD; /* DWORD 59 */ - u32 p1recvdtotalbytesMSD; /* DWORD 60 */ - u32 p1recvdtotalframes; /* DWORD 61 */ - u32 p1recvdunicastframes; /* DWORD 62 */ - u32 p1recvdmulticastframes; /* DWORD 63 */ - u32 p1recvdbroadcastframes; /* DWORD 64 */ - u32 p1crcerrors; /* DWORD 65 */ - u32 p1alignmentsymerrs; /* DWORD 66 */ - u32 p1pauseframesrecvd; /* DWORD 67 */ - u32 p1controlframesrecvd; /* DWORD 68 */ - u32 p1inrangelenerrors; /* DWORD 69 */ - u32 p1outrangeerrors; /* DWORD 70 */ - u32 p1frametoolongerrors; /* DWORD 71 */ - u32 p1droppedaddressmatch; /* DWORD 72 */ - u32 p1droppedvlanmismatch; /* DWORD 73 */ - u32 p1ipdroppedtoosmall; /* DWORD 74 */ - u32 p1ipdroppedtooshort; /* DWORD 75 */ - u32 p1ipdroppedhdrtoosmall; /* DWORD 76 */ - u32 p1tcpdroppedlen; /* DWORD 77 */ - u32 p1droppedrunt; /* DWORD 78 */ - u32 p1recvd64; /* DWORD 79 */ - u32 p1recvd65_127; /* DWORD 80 */ - u32 p1recvd128_256; /* DWORD 81 */ - u32 p1recvd256_511; /* DWORD 82 */ - u32 p1recvd512_1023; /* DWORD 83 */ - u32 p1recvd1518_1522; /* DWORD 84 */ - u32 p1recvd1522_2047; /* DWORD 85 */ - u32 p1recvd2048_4095; /* DWORD 86 */ - u32 p1recvd4096_8191; /* DWORD 87 */ - u32 p1recvd8192_9216; /* DWORD 88 */ - u32 p1rcvdipcksmerrs; /* DWORD 89 */ - u32 p1recvdtcpcksmerrs; /* DWORD 90 */ - u32 p1recvdudpcksmerrs; /* DWORD 91 */ - u32 p1recvdnonrsspackets; /* DWORD 92 */ - u32 p1recvdippackets; /* DWORD 93 */ - u32 p1recvdchute1packets; /* DWORD 94 */ - u32 p1recvdchute2packets; /* DWORD 95 */ - u32 p1recvdchute3packets; /* DWORD 96 */ - u32 p1recvdipsecpackets; /* DWORD 97 */ - u32 p1recvdmanagementpackets; /* DWORD 98 */ - u32 p1xmitbyteslsd; /* DWORD 99 */ - u32 p1xmitbytesmsd; /* DWORD 100 */ - u32 p1xmitunicastframes; /* DWORD 101 */ - u32 p1xmitmulticastframes; /* DWORD 102 */ - u32 p1xmitbroadcastframes; /* DWORD 103 */ - u32 p1xmitpauseframes; /* DWORD 104 */ - u32 p1xmitcontrolframes; /* DWORD 105 */ - u32 p1xmit64; /* DWORD 106 */ - u32 p1xmit65_127; /* DWORD 107 */ - u32 p1xmit128_256; /* DWORD 108 */ - u32 p1xmit256_511; /* DWORD 109 */ - u32 p1xmit512_1023; /* DWORD 110 */ - u32 p1xmit1518_1522; /* DWORD 111 */ - u32 p1xmit1522_2047; /* DWORD 112 */ - u32 p1xmit2048_4095; /* DWORD 113 */ - u32 p1xmit4096_8191; /* DWORD 114 */ - u32 p1xmit8192_9216; /* DWORD 115 */ - u32 p1rxfifooverflowdropped; /* DWORD 116 */ - u32 p1ipseclookupfaileddropped; /* DWORD 117 */ - u32 pxdroppednopbuf; /* DWORD 118 */ - u32 pxdroppednotxpb; /* DWORD 119 */ - u32 pxdroppednoipsecbuf; /* DWORD 120 */ - u32 pxdroppednoerxdescr; /* DWORD 121 */ - u32 pxdroppednotpredescr; /* DWORD 122 */ - u32 pxrecvdmanagementportpackets; /* DWORD 123 */ - u32 pxrecvdmanagementportbytes; /* DWORD 124 */ - u32 pxrecvdmanagementportpauseframes; /* DWORD 125 */ - u32 pxrecvdmanagementporterrors; /* DWORD 126 */ - u32 pxxmitmanagementportpackets; /* DWORD 127 */ - u32 pxxmitmanagementportbytes; /* DWORD 128 */ - u32 pxxmitmanagementportpause; /* DWORD 129 */ - u32 pxxmitmanagementportrxfifooverflow; /* DWORD 130 */ - u32 pxrecvdipsecipcksmerrs; /* DWORD 131 */ - u32 pxrecvdtcpsecipcksmerrs; /* DWORD 132 */ - u32 pxrecvdudpsecipcksmerrs; /* DWORD 133 */ - u32 pxipsecrunt; /* DWORD 134 */ - u32 pxipsecaddressmismatchdropped; /* DWORD 135 */ - u32 pxipsecrxfifooverflowdropped; /* DWORD 136 */ - u32 pxipsecframestoolong; /* DWORD 137 */ - u32 pxipsectotalipframes; /* DWORD 138 */ - u32 pxipseciptoosmall; /* DWORD 139 */ - u32 pxipseciptooshort; /* DWORD 140 */ - u32 pxipseciphdrtoosmall; /* DWORD 141 */ - u32 pxipsectcphdrbad; /* DWORD 142 */ - u32 pxrecvdipsecchute1; /* DWORD 143 */ - u32 pxrecvdipsecchute2; /* DWORD 144 */ - u32 pxrecvdipsecchute3; /* DWORD 145 */ - u32 pxdropped7frags; /* DWORD 146 */ - u32 pxdroppedfrags; /* DWORD 147 */ - u32 pxdroppedinvalidfragring; /* DWORD 148 */ - u32 pxnumforwardedpackets; /* DWORD 149 */ -} __packed; - -union MIB_ETH_STATISTICS_PARAMS { - struct MIB_ETH_STATISTICS_PARAMS_IN request; - struct BE_RXF_STATS response; -} __packed; - -/* - * Query ethernet statistics. All domains may issue this command. The - * host domain drivers may optionally reset internal statistic counters - * with a query. - */ -struct FWCMD_ETH_GET_STATISTICS { - union FWCMD_HEADER header; - union MIB_ETH_STATISTICS_PARAMS params; -} __packed; - - -struct FWCMD_ETH_ANON_175_REQUEST { - u8 port0_promiscuous; - u8 port1_promiscuous; - u16 rsvd0; -} __packed; - -struct FWCMD_ETH_ANON_176_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_ETH_ANON_174_PARAMS { - struct FWCMD_ETH_ANON_175_REQUEST request; - struct FWCMD_ETH_ANON_176_RESPONSE response; -} __packed; - -/* Enables/Disables promiscuous ethernet receive mode. */ -struct FWCMD_ETH_PROMISCUOUS { - union FWCMD_HEADER header; - union FWCMD_ETH_ANON_174_PARAMS params; -} __packed; - -struct FWCMD_ETH_ANON_178_REQUEST { - u32 new_fragsize_log2; -} __packed; - -struct FWCMD_ETH_ANON_179_RESPONSE { - u32 actual_fragsize_log2; -} __packed; - -union FWCMD_ETH_ANON_177_PARAMS { - struct FWCMD_ETH_ANON_178_REQUEST request; - struct FWCMD_ETH_ANON_179_RESPONSE response; -} __packed; - -/* - * Sets the Ethernet RX fragment size. Only host (domain 0) networking - * drivers may issue this command. This call will fail for non-host - * protection domains. In this situation the MCC CQ status will indicate - * a failure due to insufficient priviledges. The response should be - * ignored, and the driver should use the FWCMD_ETH_GET_FRAG_SIZE to - * query the existing ethernet receive fragment size. It must use this - * fragment size for all fragments in the ethernet receive ring. If - * the command succeeds, the driver must use the frag size indicated - * in the command response since the requested frag size may not be applied - * until the next reboot. When the requested fragsize matches the response - * fragsize, this indicates the request was applied immediately. - */ -struct FWCMD_ETH_SET_RX_FRAG_SIZE { - union FWCMD_HEADER header; - union FWCMD_ETH_ANON_177_PARAMS params; -} __packed; - -struct FWCMD_ETH_ANON_181_REQUEST { - u32 rsvd0; -} __packed; - -struct FWCMD_ETH_ANON_182_RESPONSE { - u32 actual_fragsize_log2; -} __packed; - -union FWCMD_ETH_ANON_180_PARAMS { - struct FWCMD_ETH_ANON_181_REQUEST request; - struct FWCMD_ETH_ANON_182_RESPONSE response; -} __packed; - -/* - * Queries the Ethernet RX fragment size. All domains may issue this - * command. The driver should call this command to determine the minimum - * required fragment size for the ethernet RX ring buffers. Drivers - * may choose to use a larger size for each fragment buffer, but BladeEngine - * will use up to the configured minimum required fragsize in each ethernet - * receive fragment buffer. For example, if the ethernet receive fragment - * size is configured to 4kB, and a driver uses 8kB fragments, a 6kB - * ethernet packet received by BladeEngine will be split accross two - * of the driver's receive framgents (4kB in one fragment buffer, and - * 2kB in the subsequent fragment buffer). - */ -struct FWCMD_ETH_GET_RX_FRAG_SIZE { - union FWCMD_HEADER header; - union FWCMD_ETH_ANON_180_PARAMS params; -} __packed; - -#endif /* __fwcmd_eth_bmap_h__ */ diff --git a/drivers/staging/benet/fwcmd_hdr_bmap.h b/drivers/staging/benet/fwcmd_hdr_bmap.h deleted file mode 100644 index 28b45328fe7b..000000000000 --- a/drivers/staging/benet/fwcmd_hdr_bmap.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_hdr_bmap_h__ -#define __fwcmd_hdr_bmap_h__ - -struct FWCMD_REQUEST_HEADER { - u8 opcode; - u8 subsystem; - u8 port_number; - u8 domain; - u32 timeout; - u32 request_length; - u32 rsvd0; -} __packed; - -struct FWCMD_RESPONSE_HEADER { - u8 opcode; - u8 subsystem; - u8 rsvd0; - u8 domain; - u8 status; - u8 additional_status; - u16 rsvd1; - u32 response_length; - u32 actual_response_length; -} __packed; - -/* - * The firmware/driver overwrites the input FWCMD_REQUEST_HEADER with - * the output FWCMD_RESPONSE_HEADER. - */ -union FWCMD_HEADER { - struct FWCMD_REQUEST_HEADER request; - struct FWCMD_RESPONSE_HEADER response; -} __packed; - -#endif /* __fwcmd_hdr_bmap_h__ */ diff --git a/drivers/staging/benet/fwcmd_mcc.h b/drivers/staging/benet/fwcmd_mcc.h deleted file mode 100644 index 9eeca878c1fb..000000000000 --- a/drivers/staging/benet/fwcmd_mcc.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_mcc_amap_h__ -#define __fwcmd_mcc_amap_h__ -#include "fwcmd_opcodes.h" -/* - * Where applicable, a WRB, may contain a list of Scatter-gather elements. - * Each element supports a 64 bit address and a 32bit length field. - */ -struct BE_MCC_SGE_AMAP { - u8 pa_lo[32]; /* DWORD 0 */ - u8 pa_hi[32]; /* DWORD 1 */ - u8 length[32]; /* DWORD 2 */ -} __packed; -struct MCC_SGE_AMAP { - u32 dw[3]; -}; -/* - * The design of an MCC_SGE allows up to 19 elements to be embedded - * in a WRB, supporting 64KB data transfers (assuming a 4KB page size). - */ -struct BE_MCC_WRB_PAYLOAD_AMAP { - union { - struct BE_MCC_SGE_AMAP sgl[19]; - u8 embedded[59][32]; /* DWORD 0 */ - }; -} __packed; -struct MCC_WRB_PAYLOAD_AMAP { - u32 dw[59]; -}; - -/* - * This is the structure of the MCC Command WRB for commands - * sent to the Management Processing Unit (MPU). See section - * for usage in embedded and non-embedded modes. - */ -struct BE_MCC_WRB_AMAP { - u8 embedded; /* DWORD 0 */ - u8 rsvd0[2]; /* DWORD 0 */ - u8 sge_count[5]; /* DWORD 0 */ - u8 rsvd1[16]; /* DWORD 0 */ - u8 special[8]; /* DWORD 0 */ - u8 payload_length[32]; /* DWORD 1 */ - u8 tag[2][32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 4 */ - struct BE_MCC_WRB_PAYLOAD_AMAP payload; -} __packed; -struct MCC_WRB_AMAP { - u32 dw[64]; -}; - -/* This is the structure of the MCC Completion queue entry */ -struct BE_MCC_CQ_ENTRY_AMAP { - u8 completion_status[16]; /* DWORD 0 */ - u8 extended_status[16]; /* DWORD 0 */ - u8 mcc_tag[2][32]; /* DWORD 1 */ - u8 rsvd0[27]; /* DWORD 3 */ - u8 consumed; /* DWORD 3 */ - u8 completed; /* DWORD 3 */ - u8 hpi_buffer_completion; /* DWORD 3 */ - u8 async_event; /* DWORD 3 */ - u8 valid; /* DWORD 3 */ -} __packed; -struct MCC_CQ_ENTRY_AMAP { - u32 dw[4]; -}; - -/* Mailbox structures used by the MPU during bootstrap */ -struct BE_MCC_MAILBOX_AMAP { - struct BE_MCC_WRB_AMAP wrb; - struct BE_MCC_CQ_ENTRY_AMAP cq; -} __packed; -struct MCC_MAILBOX_AMAP { - u32 dw[68]; -}; - -#endif /* __fwcmd_mcc_amap_h__ */ diff --git a/drivers/staging/benet/fwcmd_opcodes.h b/drivers/staging/benet/fwcmd_opcodes.h deleted file mode 100644 index 23d569386b46..000000000000 --- a/drivers/staging/benet/fwcmd_opcodes.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_opcodes_amap_h__ -#define __fwcmd_opcodes_amap_h__ - -/* - * --- FWCMD_SUBSYSTEMS --- - * The commands are grouped into the following subsystems. The subsystem - * code along with the opcode uniquely identify a particular fwcmd. - */ -#define FWCMD_SUBSYSTEM_RSVD (0) /* This subsystem is reserved. It is */ - /* never used. */ -#define FWCMD_SUBSYSTEM_COMMON (1) /* CMDs in this group are common to - * all subsystems. See - * COMMON_SUBSYSTEM_OPCODES for opcodes - * and Common Host Configuration CMDs - * for the FWCMD descriptions. - */ -#define FWCMD_SUBSYSTEM_COMMON_ISCSI (2) /* CMDs in this group are */ - /* - * common to Initiator and Target. See - * COMMON_ISCSI_SUBSYSTEM_OPCODES and - * Common iSCSI Initiator and Target - * CMDs for the command descriptions. - */ -#define FWCMD_SUBSYSTEM_ETH (3) /* This subsystem is used to - execute Ethernet commands. */ - -#define FWCMD_SUBSYSTEM_TPM (4) /* This subsystem is used - to execute TPM commands. */ -#define FWCMD_SUBSYSTEM_PXE_UNDI (5) /* This subsystem is used - * to execute PXE - * and UNDI specific commands. - */ - -#define FWCMD_SUBSYSTEM_ISCSI_INI (6) /* This subsystem is used to - execute ISCSI Initiator - specific commands. - */ -#define FWCMD_SUBSYSTEM_ISCSI_TGT (7) /* This subsystem is used - to execute iSCSI Target - specific commands.between - PTL and ARM firmware. - */ -#define FWCMD_SUBSYSTEM_MILI_PTL (8) /* This subsystem is used to - execute iSCSI Target specific - commands.between MILI - and PTL. */ -#define FWCMD_SUBSYSTEM_MILI_TMD (9) /* This subsystem is used to - execute iSCSI Target specific - commands between MILI - and TMD. */ -#define FWCMD_SUBSYSTEM_PROXY (11) /* This subsystem is used - to execute proxied commands - within the host at the - explicit request of a - non priviledged domain. - This 'subsystem' is entirely - virtual from the controller - and firmware perspective as - it is implemented in host - drivers. - */ - -/* - * --- COMMON_SUBSYSTEM_OPCODES --- - * These opcodes are common to both networking and storage PCI - * functions. They are used to reserve resources and configure - * BladeEngine. These opcodes all use the FWCMD_SUBSYSTEM_COMMON - * subsystem code. - */ -#define OPCODE_COMMON_NTWK_MAC_QUERY (1) -#define SUBSYSTEM_COMMON_NTWK_MAC_QUERY (1) -#define SUBSYSTEM_COMMON_NTWK_MAC_SET (1) -#define SUBSYSTEM_COMMON_NTWK_MULTICAST_SET (1) -#define SUBSYSTEM_COMMON_NTWK_VLAN_CONFIG (1) -#define SUBSYSTEM_COMMON_NTWK_LINK_STATUS_QUERY (1) -#define SUBSYSTEM_COMMON_READ_FLASHROM (1) -#define SUBSYSTEM_COMMON_WRITE_FLASHROM (1) -#define SUBSYSTEM_COMMON_QUERY_MAX_FWCMD_BUFFER_SIZE (1) -#define SUBSYSTEM_COMMON_ADD_PAGE_TABLES (1) -#define SUBSYSTEM_COMMON_REMOVE_PAGE_TABLES (1) -#define SUBSYSTEM_COMMON_RING_DESTROY (1) -#define SUBSYSTEM_COMMON_CQ_CREATE (1) -#define SUBSYSTEM_COMMON_EQ_CREATE (1) -#define SUBSYSTEM_COMMON_ETH_RX_CREATE (1) -#define SUBSYSTEM_COMMON_ETH_TX_CREATE (1) -#define SUBSYSTEM_COMMON_ISCSI_DEFQ_CREATE (1) -#define SUBSYSTEM_COMMON_ISCSI_WRBQ_CREATE (1) -#define SUBSYSTEM_COMMON_MCC_CREATE (1) -#define SUBSYSTEM_COMMON_JELL_CONFIG (1) -#define SUBSYSTEM_COMMON_FORCE_FAILOVER (1) -#define SUBSYSTEM_COMMON_ADD_TEMPLATE_HEADER_BUFFERS (1) -#define SUBSYSTEM_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS (1) -#define SUBSYSTEM_COMMON_POST_ZERO_BUFFER (1) -#define SUBSYSTEM_COMMON_GET_QOS (1) -#define SUBSYSTEM_COMMON_SET_QOS (1) -#define SUBSYSTEM_COMMON_TCP_GET_STATISTICS (1) -#define SUBSYSTEM_COMMON_SEEPROM_READ (1) -#define SUBSYSTEM_COMMON_TCP_STATE_QUERY (1) -#define SUBSYSTEM_COMMON_GET_CNTL_ATTRIBUTES (1) -#define SUBSYSTEM_COMMON_NOP (1) -#define SUBSYSTEM_COMMON_NTWK_RX_FILTER (1) -#define SUBSYSTEM_COMMON_GET_FW_VERSION (1) -#define SUBSYSTEM_COMMON_SET_FLOW_CONTROL (1) -#define SUBSYSTEM_COMMON_GET_FLOW_CONTROL (1) -#define SUBSYSTEM_COMMON_SET_TCP_PARAMETERS (1) -#define SUBSYSTEM_COMMON_SET_FRAME_SIZE (1) -#define SUBSYSTEM_COMMON_GET_FAT (1) -#define SUBSYSTEM_COMMON_MODIFY_EQ_DELAY (1) -#define SUBSYSTEM_COMMON_FIRMWARE_CONFIG (1) -#define SUBSYSTEM_COMMON_ENABLE_DISABLE_DOMAINS (1) -#define SUBSYSTEM_COMMON_GET_DOMAIN_CONFIG (1) -#define SUBSYSTEM_COMMON_SET_VLD_CONFIG (1) -#define SUBSYSTEM_COMMON_GET_VLD_CONFIG (1) -#define SUBSYSTEM_COMMON_GET_PORT_EQUALIZATION (1) -#define SUBSYSTEM_COMMON_SET_PORT_EQUALIZATION (1) -#define SUBSYSTEM_COMMON_RED_CONFIG (1) -#define OPCODE_COMMON_NTWK_MAC_SET (2) -#define OPCODE_COMMON_NTWK_MULTICAST_SET (3) -#define OPCODE_COMMON_NTWK_VLAN_CONFIG (4) -#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY (5) -#define OPCODE_COMMON_READ_FLASHROM (6) -#define OPCODE_COMMON_WRITE_FLASHROM (7) -#define OPCODE_COMMON_QUERY_MAX_FWCMD_BUFFER_SIZE (8) -#define OPCODE_COMMON_ADD_PAGE_TABLES (9) -#define OPCODE_COMMON_REMOVE_PAGE_TABLES (10) -#define OPCODE_COMMON_RING_DESTROY (11) -#define OPCODE_COMMON_CQ_CREATE (12) -#define OPCODE_COMMON_EQ_CREATE (13) -#define OPCODE_COMMON_ETH_RX_CREATE (14) -#define OPCODE_COMMON_ETH_TX_CREATE (15) -#define OPCODE_COMMON_NET_RESERVED0 (16) /* Reserved */ -#define OPCODE_COMMON_NET_RESERVED1 (17) /* Reserved */ -#define OPCODE_COMMON_NET_RESERVED2 (18) /* Reserved */ -#define OPCODE_COMMON_ISCSI_DEFQ_CREATE (19) -#define OPCODE_COMMON_ISCSI_WRBQ_CREATE (20) -#define OPCODE_COMMON_MCC_CREATE (21) -#define OPCODE_COMMON_JELL_CONFIG (22) -#define OPCODE_COMMON_FORCE_FAILOVER (23) -#define OPCODE_COMMON_ADD_TEMPLATE_HEADER_BUFFERS (24) -#define OPCODE_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS (25) -#define OPCODE_COMMON_POST_ZERO_BUFFER (26) -#define OPCODE_COMMON_GET_QOS (27) -#define OPCODE_COMMON_SET_QOS (28) -#define OPCODE_COMMON_TCP_GET_STATISTICS (29) -#define OPCODE_COMMON_SEEPROM_READ (30) -#define OPCODE_COMMON_TCP_STATE_QUERY (31) -#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES (32) -#define OPCODE_COMMON_NOP (33) -#define OPCODE_COMMON_NTWK_RX_FILTER (34) -#define OPCODE_COMMON_GET_FW_VERSION (35) -#define OPCODE_COMMON_SET_FLOW_CONTROL (36) -#define OPCODE_COMMON_GET_FLOW_CONTROL (37) -#define OPCODE_COMMON_SET_TCP_PARAMETERS (38) -#define OPCODE_COMMON_SET_FRAME_SIZE (39) -#define OPCODE_COMMON_GET_FAT (40) -#define OPCODE_COMMON_MODIFY_EQ_DELAY (41) -#define OPCODE_COMMON_FIRMWARE_CONFIG (42) -#define OPCODE_COMMON_ENABLE_DISABLE_DOMAINS (43) -#define OPCODE_COMMON_GET_DOMAIN_CONFIG (44) -#define OPCODE_COMMON_SET_VLD_CONFIG (45) -#define OPCODE_COMMON_GET_VLD_CONFIG (46) -#define OPCODE_COMMON_GET_PORT_EQUALIZATION (47) -#define OPCODE_COMMON_SET_PORT_EQUALIZATION (48) -#define OPCODE_COMMON_RED_CONFIG (49) - - - -/* - * --- ETH_SUBSYSTEM_OPCODES --- - * These opcodes are used for configuring the Ethernet interfaces. These - * opcodes all use the FWCMD_SUBSYSTEM_ETH subsystem code. - */ -#define OPCODE_ETH_RSS_CONFIG (1) -#define OPCODE_ETH_ACPI_CONFIG (2) -#define SUBSYSTEM_ETH_RSS_CONFIG (3) -#define SUBSYSTEM_ETH_ACPI_CONFIG (3) -#define OPCODE_ETH_PROMISCUOUS (3) -#define SUBSYSTEM_ETH_PROMISCUOUS (3) -#define SUBSYSTEM_ETH_GET_STATISTICS (3) -#define SUBSYSTEM_ETH_GET_RX_FRAG_SIZE (3) -#define SUBSYSTEM_ETH_SET_RX_FRAG_SIZE (3) -#define OPCODE_ETH_GET_STATISTICS (4) -#define OPCODE_ETH_GET_RX_FRAG_SIZE (5) -#define OPCODE_ETH_SET_RX_FRAG_SIZE (6) - - - - - -/* - * --- MCC_STATUS_CODE --- - * These are the global status codes used by all subsystems - */ -#define MCC_STATUS_SUCCESS (0) /* Indicates a successful - completion of the command */ -#define MCC_STATUS_INSUFFICIENT_PRIVILEGES (1) /* The client does not have - sufficient privileges to - execute the command */ -#define MCC_STATUS_INVALID_PARAMETER (2) /* A parameter in the command - was invalid. The extended - status contains the index - of the parameter */ -#define MCC_STATUS_INSUFFICIENT_RESOURCES (3) /* There are insufficient - chip resources to execute - the command */ -#define MCC_STATUS_QUEUE_FLUSHING (4) /* The command is completing - because the queue was - getting flushed */ -#define MCC_STATUS_DMA_FAILED (5) /* The command is completing - with a DMA error */ - -/* - * --- MGMT_ERROR_CODES --- - * Error Codes returned in the status field of the FWCMD response header - */ -#define MGMT_STATUS_SUCCESS (0) /* The FWCMD completed - without errors */ -#define MGMT_STATUS_FAILED (1) /* Error status in the Status - field of the - struct FWCMD_RESPONSE_HEADER */ -#define MGMT_STATUS_ILLEGAL_REQUEST (2) /* Invalid FWCMD opcode */ -#define MGMT_STATUS_ILLEGAL_FIELD (3) /* Invalid parameter in - the FWCMD payload */ - -#endif /* __fwcmd_opcodes_amap_h__ */ diff --git a/drivers/staging/benet/fwcmd_types_bmap.h b/drivers/staging/benet/fwcmd_types_bmap.h deleted file mode 100644 index 92217aff3a16..000000000000 --- a/drivers/staging/benet/fwcmd_types_bmap.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_types_bmap_h__ -#define __fwcmd_types_bmap_h__ - -/* MAC address format */ -struct MAC_ADDRESS_FORMAT { - u16 SizeOfStructure; - u8 MACAddress[6]; -} __packed; - -#endif /* __fwcmd_types_bmap_h__ */ diff --git a/drivers/staging/benet/host_struct.h b/drivers/staging/benet/host_struct.h deleted file mode 100644 index 3de6722b980f..000000000000 --- a/drivers/staging/benet/host_struct.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __host_struct_amap_h__ -#define __host_struct_amap_h__ -#include "be_cm.h" -#include "be_common.h" -#include "descriptors.h" - -/* --- EQ_COMPLETION_MAJOR_CODE_ENUM --- */ -#define EQ_MAJOR_CODE_COMPLETION (0) /* Completion event on a */ - /* qcompletion ueue. */ -#define EQ_MAJOR_CODE_ETH (1) /* Affiliated Ethernet Event. */ -#define EQ_MAJOR_CODE_RESERVED (2) /* Reserved */ -#define EQ_MAJOR_CODE_RDMA (3) /* Affiliated RDMA Event. */ -#define EQ_MAJOR_CODE_ISCSI (4) /* Affiliated ISCSI Event */ -#define EQ_MAJOR_CODE_UNAFFILIATED (5) /* Unaffiliated Event */ - -/* --- EQ_COMPLETION_MINOR_CODE_ENUM --- */ -#define EQ_MINOR_CODE_COMPLETION (0) /* Completion event on a */ - /* completion queue. */ -#define EQ_MINOR_CODE_OTHER (1) /* Other Event (TBD). */ - -/* Queue Entry Definition for all 4 byte event queue types. */ -struct BE_EQ_ENTRY_AMAP { - u8 Valid; /* DWORD 0 */ - u8 MajorCode[3]; /* DWORD 0 */ - u8 MinorCode[12]; /* DWORD 0 */ - u8 ResourceID[16]; /* DWORD 0 */ -} __packed; -struct EQ_ENTRY_AMAP { - u32 dw[1]; -}; - -/* - * --- ETH_EVENT_CODE --- - * These codes are returned by the MPU when one of these events has occurred, - * and the event is configured to report to an Event Queue when an event - * is detected. - */ -#define ETH_EQ_LINK_STATUS (0) /* Link status change event */ - /* detected. */ -#define ETH_EQ_WATERMARK (1) /* watermark event detected. */ -#define ETH_EQ_MAGIC_PKT (2) /* magic pkt event detected. */ -#define ETH_EQ_ACPI_PKT0 (3) /* ACPI interesting packet */ - /* detected. */ -#define ETH_EQ_ACPI_PKT1 (3) /* ACPI interesting packet */ - /* detected. */ -#define ETH_EQ_ACPI_PKT2 (3) /* ACPI interesting packet */ - /* detected. */ -#define ETH_EQ_ACPI_PKT3 (3) /* ACPI interesting packet */ - /* detected. */ - -/* - * --- ETH_TX_COMPL_STATUS_ENUM --- - * Status codes contained in Ethernet TX completion descriptors. - */ -#define ETH_COMP_VALID (0) -#define ETH_COMP_ERROR (1) -#define ETH_COMP_INVALID (15) - -/* - * --- ETH_TX_COMPL_PORT_ENUM --- - * Port indicator contained in Ethernet TX completion descriptors. - */ -#define ETH_COMP_PORT0 (0) -#define ETH_COMP_PORT1 (1) -#define ETH_COMP_MGMT (2) - -/* - * --- ETH_TX_COMPL_CT_ENUM --- - * Completion type indicator contained in Ethernet TX completion descriptors. - */ -#define ETH_COMP_ETH (0) - -/* - * Work request block that the driver issues to the chip for - * Ethernet transmissions. All control fields must be valid in each WRB for - * a message. The controller, as specified by the flags, optionally writes - * an entry to the Completion Ring and generate an event. - */ -struct BE_ETH_WRB_AMAP { - u8 frag_pa_hi[32]; /* DWORD 0 */ - u8 frag_pa_lo[32]; /* DWORD 1 */ - u8 complete; /* DWORD 2 */ - u8 event; /* DWORD 2 */ - u8 crc; /* DWORD 2 */ - u8 forward; /* DWORD 2 */ - u8 ipsec; /* DWORD 2 */ - u8 mgmt; /* DWORD 2 */ - u8 ipcs; /* DWORD 2 */ - u8 udpcs; /* DWORD 2 */ - u8 tcpcs; /* DWORD 2 */ - u8 lso; /* DWORD 2 */ - u8 last; /* DWORD 2 */ - u8 vlan; /* DWORD 2 */ - u8 dbg[3]; /* DWORD 2 */ - u8 hash_val[3]; /* DWORD 2 */ - u8 lso_mss[14]; /* DWORD 2 */ - u8 frag_len[16]; /* DWORD 3 */ - u8 vlan_tag[16]; /* DWORD 3 */ -} __packed; -struct ETH_WRB_AMAP { - u32 dw[4]; -}; - -/* This is an Ethernet transmit completion descriptor */ -struct BE_ETH_TX_COMPL_AMAP { - u8 user_bytes[16]; /* DWORD 0 */ - u8 nwh_bytes[8]; /* DWORD 0 */ - u8 lso; /* DWORD 0 */ - u8 rsvd0[7]; /* DWORD 0 */ - u8 wrb_index[16]; /* DWORD 1 */ - u8 ct[2]; /* DWORD 1 */ - u8 port[2]; /* DWORD 1 */ - u8 rsvd1[8]; /* DWORD 1 */ - u8 status[4]; /* DWORD 1 */ - u8 rsvd2[16]; /* DWORD 2 */ - u8 ringid[11]; /* DWORD 2 */ - u8 hash_val[4]; /* DWORD 2 */ - u8 valid; /* DWORD 2 */ - u8 rsvd3[32]; /* DWORD 3 */ -} __packed; -struct ETH_TX_COMPL_AMAP { - u32 dw[4]; -}; - -/* Ethernet Receive Buffer descriptor */ -struct BE_ETH_RX_D_AMAP { - u8 fragpa_hi[32]; /* DWORD 0 */ - u8 fragpa_lo[32]; /* DWORD 1 */ -} __packed; -struct ETH_RX_D_AMAP { - u32 dw[2]; -}; - -/* This is an Ethernet Receive Completion Descriptor */ -struct BE_ETH_RX_COMPL_AMAP { - u8 vlan_tag[16]; /* DWORD 0 */ - u8 pktsize[14]; /* DWORD 0 */ - u8 port; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 err; /* DWORD 1 */ - u8 rsshp; /* DWORD 1 */ - u8 ipf; /* DWORD 1 */ - u8 tcpf; /* DWORD 1 */ - u8 udpf; /* DWORD 1 */ - u8 ipcksm; /* DWORD 1 */ - u8 tcpcksm; /* DWORD 1 */ - u8 udpcksm; /* DWORD 1 */ - u8 macdst[6]; /* DWORD 1 */ - u8 vtp; /* DWORD 1 */ - u8 vtm; /* DWORD 1 */ - u8 fragndx[10]; /* DWORD 1 */ - u8 ct[2]; /* DWORD 1 */ - u8 ipsec; /* DWORD 1 */ - u8 numfrags[3]; /* DWORD 1 */ - u8 rsvd1[31]; /* DWORD 2 */ - u8 valid; /* DWORD 2 */ - u8 rsshash[32]; /* DWORD 3 */ -} __packed; -struct ETH_RX_COMPL_AMAP { - u32 dw[4]; -}; - -#endif /* __host_struct_amap_h__ */ diff --git a/drivers/staging/benet/hwlib.h b/drivers/staging/benet/hwlib.h deleted file mode 100644 index afedf4dc5903..000000000000 --- a/drivers/staging/benet/hwlib.h +++ /dev/null @@ -1,830 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#ifndef __hwlib_h__ -#define __hwlib_h__ - -#include -#include -#include -#include - -#include "regmap.h" /* srcgen array map output */ - -#include "asyncmesg.h" -#include "fwcmd_opcodes.h" -#include "post_codes.h" -#include "fwcmd_mcc.h" - -#include "fwcmd_types_bmap.h" -#include "fwcmd_common_bmap.h" -#include "fwcmd_eth_bmap.h" -#include "bestatus.h" -/* - * - * Macros for reading/writing a protection domain or CSR registers - * in BladeEngine. - */ -#define PD_READ(fo, field) ioread32((fo)->db_va + \ - offsetof(struct BE_PROTECTION_DOMAIN_DBMAP_AMAP, field)/8) - -#define PD_WRITE(fo, field, val) iowrite32(val, (fo)->db_va + \ - offsetof(struct BE_PROTECTION_DOMAIN_DBMAP_AMAP, field)/8) - -#define CSR_READ(fo, field) ioread32((fo)->csr_va + \ - offsetof(struct BE_BLADE_ENGINE_CSRMAP_AMAP, field)/8) - -#define CSR_WRITE(fo, field, val) iowrite32(val, (fo)->csr_va + \ - offsetof(struct BE_BLADE_ENGINE_CSRMAP_AMAP, field)/8) - -#define PCICFG0_READ(fo, field) ioread32((fo)->pci_va + \ - offsetof(struct BE_PCICFG0_CSRMAP_AMAP, field)/8) - -#define PCICFG0_WRITE(fo, field, val) iowrite32(val, (fo)->pci_va + \ - offsetof(struct BE_PCICFG0_CSRMAP_AMAP, field)/8) - -#define PCICFG1_READ(fo, field) ioread32((fo)->pci_va + \ - offsetof(struct BE_PCICFG1_CSRMAP_AMAP, field)/8) - -#define PCICFG1_WRITE(fo, field, val) iowrite32(val, (fo)->pci_va + \ - offsetof(struct BE_PCICFG1_CSRMAP_AMAP, field)/8) - -#ifdef BE_DEBUG -#define ASSERT(c) BUG_ON(!(c)); -#else -#define ASSERT(c) -#endif - -/* debug levels */ -enum BE_DEBUG_LEVELS { - DL_ALWAYS = 0, /* cannot be masked */ - DL_ERR = 0x1, /* errors that should never happen */ - DL_WARN = 0x2, /* something questionable. - recoverable errors */ - DL_NOTE = 0x4, /* infrequent, important debug info */ - DL_INFO = 0x8, /* debug information */ - DL_VERBOSE = 0x10, /* detailed info, such as buffer traces */ - BE_DL_MIN_VALUE = 0x1, /* this is the min value used */ - BE_DL_MAX_VALUE = 0x80 /* this is the higheset value used */ -} ; - -extern unsigned int trace_level; - -#define TRACE(lm, fmt, args...) { \ - if (trace_level & lm) { \ - printk(KERN_NOTICE "BE: %s:%d \n" fmt, \ - __FILE__ , __LINE__ , ## args); \ - } \ - } - -static inline unsigned int be_trace_set_level(unsigned int level) -{ - unsigned int old_level = trace_level; - trace_level = level; - return old_level; -} - -#define be_trace_get_level() trace_level -/* - * Returns number of pages spanned by the size of data - * starting at the given address. - */ -#define PAGES_SPANNED(_address, _size) \ - ((u32)((((size_t)(_address) & (PAGE_SIZE - 1)) + \ - (_size) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)) -/* Byte offset into the page corresponding to given address */ -#define OFFSET_IN_PAGE(_addr_) ((size_t)(_addr_) & (PAGE_SIZE-1)) - -/* - * circular subtract. - * Returns a - b assuming a circular number system, where a and b are - * in range (0, maxValue-1). If a==b, zero is returned so the - * highest value possible with this subtraction is maxValue-1. - */ -static inline u32 be_subc(u32 a, u32 b, u32 max) -{ - ASSERT(a <= max && b <= max); - ASSERT(max > 0); - return a >= b ? (a - b) : (max - b + a); -} - -static inline u32 be_addc(u32 a, u32 b, u32 max) -{ - ASSERT(a < max); - ASSERT(max > 0); - return (max - a > b) ? (a + b) : (b + a - max); -} - -/* descriptor for a physically contiguous memory used for ring */ -struct ring_desc { - u32 length; /* length in bytes */ - void *va; /* virtual address */ - u64 pa; /* bus address */ -} ; - -/* - * This structure stores information about a ring shared between hardware - * and software. Each ring is allocated by the driver in the uncached - * extension and mapped into BladeEngine's unified table. - */ -struct mp_ring { - u32 pages; /* queue size in pages */ - u32 id; /* queue id assigned by beklib */ - u32 num; /* number of elements in queue */ - u32 cidx; /* consumer index */ - u32 pidx; /* producer index -- not used by most rings */ - u32 itemSize; /* size in bytes of one object */ - - void *va; /* The virtual address of the ring. - This should be last to allow 32 & 64 - bit debugger extensions to work. */ -} ; - -/*----------- amap bit filed get / set macros and functions -----*/ -/* - * Structures defined in the map header files (under fw/amap/) with names - * in the format BE__AMAP are pseudo structures with members - * of type u8. These structures are templates that are used in - * conjuntion with the structures with names in the format - * _AMAP to calculate the bit masks and bit offsets to get or set - * bit fields in structures. The structures _AMAP are arrays - * of 32 bits words and have the correct size. The following macros - * provide convenient ways to get and set the various members - * in the structures without using strucctures with bit fields. - * Always use the macros AMAP_GET_BITS_PTR and AMAP_SET_BITS_PTR - * macros to extract and set various members. - */ - -/* - * Returns the a bit mask for the register that is NOT shifted into location. - * That means return values always look like: 0x1, 0xFF, 0x7FF, etc... - */ -static inline u32 amap_mask(u32 bit_size) -{ - return bit_size == 32 ? 0xFFFFFFFF : (1 << bit_size) - 1; -} - -#define AMAP_BIT_MASK(_struct_, field) \ - amap_mask(AMAP_BIT_SIZE(_struct_, field)) - -/* - * non-optimized set bits function. First clears the bits and then assigns them. - * This does not require knowledge of the particular DWORD you are setting. - * e.g. AMAP_SET_BITS_PTR (struct, field1, &contextMemory, 123); - */ -static inline void -amap_set(void *ptr, u32 dw_offset, u32 mask, u32 offset, u32 value) -{ - u32 *dw = (u32 *)ptr; - *(dw + dw_offset) &= ~(mask << offset); - *(dw + dw_offset) |= (mask & value) << offset; -} - -#define AMAP_SET_BITS_PTR(_struct_, field, _structPtr_, val) \ - amap_set(_structPtr_, AMAP_WORD_OFFSET(_struct_, field),\ - AMAP_BIT_MASK(_struct_, field), \ - AMAP_BIT_OFFSET(_struct_, field), val) -/* - * Non-optimized routine that gets the bits without knowing the correct DWORD. - * e.g. fieldValue = AMAP_GET_BITS_PTR (struct, field1, &contextMemory); - */ -static inline u32 -amap_get(void *ptr, u32 dw_offset, u32 mask, u32 offset) -{ - u32 *dw = (u32 *)ptr; - return mask & (*(dw + dw_offset) >> offset); -} -#define AMAP_GET_BITS_PTR(_struct_, field, _structPtr_) \ - amap_get(_structPtr_, AMAP_WORD_OFFSET(_struct_, field), \ - AMAP_BIT_MASK(_struct_, field), \ - AMAP_BIT_OFFSET(_struct_, field)) - -/* Returns 0-31 representing bit offset within a DWORD of a bitfield. */ -#define AMAP_BIT_OFFSET(_struct_, field) \ - (offsetof(struct BE_ ## _struct_ ## _AMAP, field) % 32) - -/* Returns 0-n representing DWORD offset of bitfield within the structure. */ -#define AMAP_WORD_OFFSET(_struct_, field) \ - (offsetof(struct BE_ ## _struct_ ## _AMAP, field)/32) - -/* Returns size of bitfield in bits. */ -#define AMAP_BIT_SIZE(_struct_, field) \ - sizeof(((struct BE_ ## _struct_ ## _AMAP*)0)->field) - -struct be_mcc_wrb_response_copy { - u16 length; /* bytes in response */ - u16 fwcmd_offset; /* offset within the wrb of the response */ - void *va; /* user's va to copy response into */ - -} ; -typedef void (*mcc_wrb_cqe_callback) (void *context, int status, - struct MCC_WRB_AMAP *optional_wrb); -struct be_mcc_wrb_context { - - mcc_wrb_cqe_callback internal_cb; /* Function to call on - completion */ - void *internal_cb_context; /* Parameter to pass - to completion function */ - - mcc_wrb_cqe_callback cb; /* Function to call on completion */ - void *cb_context; /* Parameter to pass to completion function */ - - int *users_final_status; /* pointer to a local - variable for synchronous - commands */ - struct MCC_WRB_AMAP *wrb; /* pointer to original wrb for embedded - commands only */ - struct list_head next; /* links context structs together in - free list */ - - struct be_mcc_wrb_response_copy copy; /* Optional parameters to copy - embedded response to user's va */ - -#if defined(BE_DEBUG) - u16 subsystem, opcode; /* Track this FWCMD for debug builds. */ - struct MCC_WRB_AMAP *ring_wrb; - u32 consumed_count; -#endif -} ; - -/* - Represents a function object for network or storage. This - is used to manage per-function resources like MCC CQs, etc. -*/ -struct be_function_object { - - u32 magic; /*!< magic for detecting memory corruption. */ - - /* PCI BAR mapped addresses */ - u8 __iomem *csr_va; /* CSR */ - u8 __iomem *db_va; /* Door Bell */ - u8 __iomem *pci_va; /* PCI config space */ - u32 emulate; /* if set, MPU is not available. - Emulate everything. */ - u32 pend_queue_driving; /* if set, drive the queued WRBs - after releasing the WRB lock */ - - spinlock_t post_lock; /* lock for verifying one thread posting wrbs */ - spinlock_t cq_lock; /* lock for verifying one thread - processing cq */ - spinlock_t mcc_context_lock; /* lock for protecting mcc - context free list */ - unsigned long post_irq; - unsigned long cq_irq; - - u32 type; - u32 pci_function_number; - - struct be_mcc_object *mcc; /* mcc rings. */ - - struct { - struct MCC_MAILBOX_AMAP *va; /* VA to the mailbox */ - u64 pa; /* PA to the mailbox */ - u32 length; /* byte length of mailbox */ - - /* One default context struct used for posting at - * least one MCC_WRB - */ - struct be_mcc_wrb_context default_context; - bool default_context_allocated; - } mailbox; - - struct { - - /* Wake on lans configured. */ - u32 wol_bitmask; /* bits 0,1,2,3 are set if - corresponding index is enabled */ - } config; - - - struct BE_FIRMWARE_CONFIG fw_config; -} ; - -/* - Represents an Event Queue -*/ -struct be_eq_object { - u32 magic; - atomic_t ref_count; - - struct be_function_object *parent_function; - - struct list_head eq_list; - struct list_head cq_list_head; - - u32 eq_id; - void *cb_context; - -} ; - -/* - Manages a completion queue -*/ -struct be_cq_object { - u32 magic; - atomic_t ref_count; - - struct be_function_object *parent_function; - struct be_eq_object *eq_object; - - struct list_head cq_list; - struct list_head cqlist_for_eq; - - void *va; - u32 num_entries; - - void *cb_context; - - u32 cq_id; - -} ; - -/* - Manages an ethernet send queue -*/ -struct be_ethsq_object { - u32 magic; - - struct list_head list; - - struct be_function_object *parent_function; - struct be_cq_object *cq_object; - u32 bid; - -} ; - -/* -@brief - Manages an ethernet receive queue -*/ -struct be_ethrq_object { - u32 magic; - struct list_head list; - struct be_function_object *parent_function; - u32 rid; - struct be_cq_object *cq_object; - struct be_cq_object *rss_cq_object[4]; - -} ; - -/* - Manages an MCC -*/ -typedef void (*mcc_async_event_callback) (void *context, u32 event_code, - void *event); -struct be_mcc_object { - u32 magic; - - struct be_function_object *parent_function; - struct list_head mcc_list; - - struct be_cq_object *cq_object; - - /* Async event callback for MCC CQ. */ - mcc_async_event_callback async_cb; - void *async_context; - - struct { - struct be_mcc_wrb_context *base; - u32 num; - struct list_head list_head; - } wrb_context; - - struct { - struct ring_desc *rd; - struct mp_ring ring; - } sq; - - struct { - struct mp_ring ring; - } cq; - - u32 processing; /* flag indicating that one thread - is processing CQ */ - u32 rearm; /* doorbell rearm setting to make - sure the active processing thread */ - /* rearms the CQ if any of the threads requested it. */ - - struct list_head backlog; - u32 backlog_length; - u32 driving_backlog; - u32 consumed_index; - -} ; - - -/* Queue context header -- the required software information for - * queueing a WRB. - */ -struct be_queue_driver_context { - mcc_wrb_cqe_callback internal_cb; /* Function to call on - completion */ - void *internal_cb_context; /* Parameter to pass - to completion function */ - - mcc_wrb_cqe_callback cb; /* Function to call on completion */ - void *cb_context; /* Parameter to pass to completion function */ - - struct be_mcc_wrb_response_copy copy; /* Optional parameters to copy - embedded response to user's va */ - void *optional_fwcmd_va; - struct list_head list; - u32 bytes; -} ; - -/* - * Common MCC WRB header that all commands require. - */ -struct be_mcc_wrb_header { - u8 rsvd[offsetof(struct BE_MCC_WRB_AMAP, payload)/8]; -} ; - -/* - * All non embedded commands supported by hwlib functions only allow - * 1 SGE. This queue context handles them all. - */ -struct be_nonembedded_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct MCC_SGE_AMAP sge[1]; -} ; - -/* - * ------------------------------------------------------------------------ - * This section contains the specific queue struct for each command. - * The user could always provide a be_generic_q_ctxt but this is a - * rather large struct. By using the specific struct, memory consumption - * can be reduced. - * ------------------------------------------------------------------------ - */ - -struct be_link_status_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY fwcmd; -} ; - -struct be_multicast_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_MULTICAST_SET fwcmd; -} ; - - -struct be_vlan_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_VLAN_CONFIG fwcmd; -} ; - -struct be_promiscuous_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_ETH_PROMISCUOUS fwcmd; -} ; - -struct be_force_failover_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_FORCE_FAILOVER fwcmd; -} ; - - -struct be_rxf_filter_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_RX_FILTER fwcmd; -} ; - -struct be_eq_modify_delay_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_MODIFY_EQ_DELAY fwcmd; -} ; - -/* - * The generic context is the largest size that would be required. - * It is the software context plus an entire WRB. - */ -struct be_generic_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct MCC_WRB_PAYLOAD_AMAP payload; -} ; - -/* - * Types for the BE_QUEUE_CONTEXT object. - */ -#define BE_QUEUE_INVALID (0) -#define BE_QUEUE_LINK_STATUS (0xA006) -#define BE_QUEUE_ETH_STATS (0xA007) -#define BE_QUEUE_TPM_STATS (0xA008) -#define BE_QUEUE_TCP_STATS (0xA009) -#define BE_QUEUE_MULTICAST (0xA00A) -#define BE_QUEUE_VLAN (0xA00B) -#define BE_QUEUE_RSS (0xA00C) -#define BE_QUEUE_FORCE_FAILOVER (0xA00D) -#define BE_QUEUE_PROMISCUOUS (0xA00E) -#define BE_QUEUE_WAKE_ON_LAN (0xA00F) -#define BE_QUEUE_NOP (0xA010) - -/* --- BE_FUNCTION_ENUM --- */ -#define BE_FUNCTION_TYPE_ISCSI (0) -#define BE_FUNCTION_TYPE_NETWORK (1) -#define BE_FUNCTION_TYPE_ARM (2) - -/* --- BE_ETH_TX_RING_TYPE_ENUM --- */ -#define BE_ETH_TX_RING_TYPE_FORWARDING (1) /* Ether ring for forwarding */ -#define BE_ETH_TX_RING_TYPE_STANDARD (2) /* Ether ring for sending */ - /* network packets. */ -#define BE_ETH_TX_RING_TYPE_BOUND (3) /* Ethernet ring for sending */ - /* network packets, bound */ - /* to a physical port. */ -/* - * ---------------------------------------------------------------------- - * API MACROS - * ---------------------------------------------------------------------- - */ -#define BE_FWCMD_NAME(_short_name_) struct FWCMD_##_short_name_ -#define BE_OPCODE_NAME(_short_name_) OPCODE_##_short_name_ -#define BE_SUBSYSTEM_NAME(_short_name_) SUBSYSTEM_##_short_name_ - - -#define BE_PREPARE_EMBEDDED_FWCMD(_pfob_, _wrb_, _short_name_) \ - ((BE_FWCMD_NAME(_short_name_) *) \ - be_function_prepare_embedded_fwcmd(_pfob_, _wrb_, \ - sizeof(BE_FWCMD_NAME(_short_name_)), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.request), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.response), \ - BE_OPCODE_NAME(_short_name_), \ - BE_SUBSYSTEM_NAME(_short_name_))); - -#define BE_PREPARE_NONEMBEDDED_FWCMD(_pfob_, _wrb_, _iva_, _ipa_, _short_name_)\ - ((BE_FWCMD_NAME(_short_name_) *) \ - be_function_prepare_nonembedded_fwcmd(_pfob_, _wrb_, (_iva_), (_ipa_), \ - sizeof(BE_FWCMD_NAME(_short_name_)), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.request), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.response), \ - BE_OPCODE_NAME(_short_name_), \ - BE_SUBSYSTEM_NAME(_short_name_))); - -int be_function_object_create(u8 __iomem *csr_va, u8 __iomem *db_va, - u8 __iomem *pci_va, u32 function_type, struct ring_desc *mailbox_rd, - struct be_function_object *pfob); - -int be_function_object_destroy(struct be_function_object *pfob); -int be_function_cleanup(struct be_function_object *pfob); - - -int be_function_get_fw_version(struct be_function_object *pfob, - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD *fw_version, - mcc_wrb_cqe_callback cb, void *cb_context); - - -int be_eq_modify_delay(struct be_function_object *pfob, - u32 num_eq, struct be_eq_object **eq_array, - u32 *eq_delay_array, mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_eq_modify_delay_q_ctxt *q_ctxt); - - - -int be_eq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 eqe_size, u32 num_entries, - u32 watermark, u32 timer_delay, struct be_eq_object *eq_object); - -int be_eq_destroy(struct be_eq_object *eq); - -int be_cq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, - bool solicited_eventable, bool no_delay, - u32 wm_thresh, struct be_eq_object *eq_object, - struct be_cq_object *cq_object); - -int be_cq_destroy(struct be_cq_object *cq); - -int be_mcc_ring_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, - struct be_mcc_wrb_context *context_array, - u32 num_context_entries, - struct be_cq_object *cq, struct be_mcc_object *mcc); -int be_mcc_ring_destroy(struct be_mcc_object *mcc_object); - -int be_mcc_process_cq(struct be_mcc_object *mcc_object, bool rearm); - -int be_mcc_add_async_event_callback(struct be_mcc_object *mcc_object, - mcc_async_event_callback cb, void *cb_context); - -int be_pci_soft_reset(struct be_function_object *pfob); - - -int be_drive_POST(struct be_function_object *pfob); - - -int be_eth_sq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length_in_bytes, - u32 type, u32 ulp, struct be_cq_object *cq_object, - struct be_ethsq_object *eth_sq); - -struct be_eth_sq_parameters { - u32 port; - u32 rsvd0[2]; -} ; - -int be_eth_sq_create_ex(struct be_function_object *pfob, - struct ring_desc *rd, u32 length_in_bytes, - u32 type, u32 ulp, struct be_cq_object *cq_object, - struct be_eth_sq_parameters *ex_parameters, - struct be_ethsq_object *eth_sq); -int be_eth_sq_destroy(struct be_ethsq_object *eth_sq); - -int be_eth_set_flow_control(struct be_function_object *pfob, - bool txfc_enable, bool rxfc_enable); - -int be_eth_get_flow_control(struct be_function_object *pfob, - bool *txfc_enable, bool *rxfc_enable); -int be_eth_set_qos(struct be_function_object *pfob, u32 max_bps, u32 max_pps); - -int be_eth_get_qos(struct be_function_object *pfob, u32 *max_bps, u32 *max_pps); - -int be_eth_set_frame_size(struct be_function_object *pfob, - u32 *tx_frame_size, u32 *rx_frame_size); - -int be_eth_rq_create(struct be_function_object *pfob, - struct ring_desc *rd, struct be_cq_object *cq_object, - struct be_cq_object *bcmc_cq_object, - struct be_ethrq_object *eth_rq); - -int be_eth_rq_destroy(struct be_ethrq_object *eth_rq); - -int be_eth_rq_destroy_options(struct be_ethrq_object *eth_rq, bool flush, - mcc_wrb_cqe_callback cb, void *cb_context); -int be_eth_rq_set_frag_size(struct be_function_object *pfob, - u32 new_frag_size_bytes, u32 *actual_frag_size_bytes); -int be_eth_rq_get_frag_size(struct be_function_object *pfob, - u32 *frag_size_bytes); - -void *be_function_prepare_embedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - u32 payload_length, u32 request_length, - u32 response_length, u32 opcode, u32 subsystem); -void *be_function_prepare_nonembedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, void *fwcmd_header_va, u64 fwcmd_header_pa, - u32 payload_length, u32 request_length, u32 response_length, - u32 opcode, u32 subsystem); - - -struct MCC_WRB_AMAP * -be_function_peek_mcc_wrb(struct be_function_object *pfob); - -int be_rxf_mac_address_read_write(struct be_function_object *pfob, - bool port1, bool mac1, bool mgmt, - bool write, bool permanent, u8 *mac_address, - mcc_wrb_cqe_callback cb, - void *cb_context); - -int be_rxf_multicast_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u8 *mac_table, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_multicast_q_ctxt *q_ctxt); - -int be_rxf_vlan_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u16 *vlan_tag_array, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_vlan_q_ctxt *q_ctxt); - - -int be_rxf_link_status(struct be_function_object *pfob, - struct BE_LINK_STATUS *link_status, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_link_status_q_ctxt *q_ctxt); - - -int be_rxf_query_eth_statistics(struct be_function_object *pfob, - struct FWCMD_ETH_GET_STATISTICS *va_for_fwcmd, - u64 pa_for_fwcmd, mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_nonembedded_q_ctxt *q_ctxt); - -int be_rxf_promiscuous(struct be_function_object *pfob, - bool enable_port0, bool enable_port1, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_promiscuous_q_ctxt *q_ctxt); - - -int be_rxf_filter_config(struct be_function_object *pfob, - struct NTWK_RX_FILTER_SETTINGS *settings, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_rxf_filter_q_ctxt *q_ctxt); - -/* - * ------------------------------------------------------ - * internal functions used by hwlib - * ------------------------------------------------------ - */ - - -int be_function_ring_destroy(struct be_function_object *pfob, - u32 id, u32 ring_type, mcc_wrb_cqe_callback cb, - void *cb_context, - mcc_wrb_cqe_callback internal_cb, - void *internal_callback_context); - -int be_function_post_mcc_wrb(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - struct be_generic_q_ctxt *q_ctxt, - mcc_wrb_cqe_callback cb, void *cb_context, - mcc_wrb_cqe_callback internal_cb, - void *internal_cb_context, void *optional_fwcmd_va, - struct be_mcc_wrb_response_copy *response_copy); - -int be_function_queue_mcc_wrb(struct be_function_object *pfob, - struct be_generic_q_ctxt *q_ctxt); - -/* - * ------------------------------------------------------ - * MCC QUEUE - * ------------------------------------------------------ - */ - -int be_mpu_init_mailbox(struct be_function_object *pfob, struct ring_desc *rd); - - -struct MCC_WRB_AMAP * -_be_mpu_peek_ring_wrb(struct be_mcc_object *mcc, bool driving_queue); - -struct be_mcc_wrb_context * -_be_mcc_allocate_wrb_context(struct be_function_object *pfob); - -void _be_mcc_free_wrb_context(struct be_function_object *pfob, - struct be_mcc_wrb_context *context); - -int _be_mpu_post_wrb_mailbox(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context); - -int _be_mpu_post_wrb_ring(struct be_mcc_object *mcc, - struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context); - -void be_drive_mcc_wrb_queue(struct be_mcc_object *mcc); - - -/* - * ------------------------------------------------------ - * Ring Sizes - * ------------------------------------------------------ - */ -static inline u32 be_ring_encoding_to_length(u32 encoding, u32 object_size) -{ - - ASSERT(encoding != 1); /* 1 is rsvd */ - ASSERT(encoding < 16); - ASSERT(object_size > 0); - - if (encoding == 0) /* 32k deep */ - encoding = 16; - - return (1 << (encoding - 1)) * object_size; -} - -static inline -u32 be_ring_length_to_encoding(u32 length_in_bytes, u32 object_size) -{ - - u32 count, encoding; - - ASSERT(object_size > 0); - ASSERT(length_in_bytes % object_size == 0); - - count = length_in_bytes / object_size; - - ASSERT(count > 1); - ASSERT(count <= 32 * 1024); - ASSERT(length_in_bytes <= 8 * PAGE_SIZE); /* max ring size in UT */ - - encoding = __ilog2_u32(count) + 1; - - if (encoding == 16) - encoding = 0; /* 32k deep */ - - return encoding; -} - -void be_rd_to_pa_list(struct ring_desc *rd, struct PHYS_ADDR *pa_list, - u32 max_num); -#endif /* __hwlib_h__ */ diff --git a/drivers/staging/benet/mpu.c b/drivers/staging/benet/mpu.c deleted file mode 100644 index 269cc11d3055..000000000000 --- a/drivers/staging/benet/mpu.c +++ /dev/null @@ -1,1364 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include -#include "hwlib.h" -#include "bestatus.h" - -static -inline void mp_ring_create(struct mp_ring *ring, u32 num, u32 size, void *va) -{ - ASSERT(ring); - memset(ring, 0, sizeof(struct mp_ring)); - ring->num = num; - ring->pages = DIV_ROUND_UP(num * size, PAGE_SIZE); - ring->itemSize = size; - ring->va = va; -} - -/* - * ----------------------------------------------------------------------- - * Interface for 2 index rings. i.e. consumer/producer rings - * -------------------------------------------------------------------------- - */ - -/* Returns number items pending on ring. */ -static inline u32 mp_ring_num_pending(struct mp_ring *ring) -{ - ASSERT(ring); - if (ring->num == 0) - return 0; - return be_subc(ring->pidx, ring->cidx, ring->num); -} - -/* Returns number items free on ring. */ -static inline u32 mp_ring_num_empty(struct mp_ring *ring) -{ - ASSERT(ring); - return ring->num - 1 - mp_ring_num_pending(ring); -} - -/* Consume 1 item */ -static inline void mp_ring_consume(struct mp_ring *ring) -{ - ASSERT(ring); - ASSERT(ring->pidx != ring->cidx); - - ring->cidx = be_addc(ring->cidx, 1, ring->num); -} - -/* Produce 1 item */ -static inline void mp_ring_produce(struct mp_ring *ring) -{ - ASSERT(ring); - ring->pidx = be_addc(ring->pidx, 1, ring->num); -} - -/* Consume count items */ -static inline void mp_ring_consume_multiple(struct mp_ring *ring, u32 count) -{ - ASSERT(ring); - ASSERT(mp_ring_num_pending(ring) >= count); - ring->cidx = be_addc(ring->cidx, count, ring->num); -} - -static inline void *mp_ring_item(struct mp_ring *ring, u32 index) -{ - ASSERT(ring); - ASSERT(index < ring->num); - ASSERT(ring->itemSize > 0); - return (u8 *) ring->va + index * ring->itemSize; -} - -/* Ptr to produce item */ -static inline void *mp_ring_producer_ptr(struct mp_ring *ring) -{ - ASSERT(ring); - return mp_ring_item(ring, ring->pidx); -} - -/* - * Returns a pointer to the current location in the ring. - * This is used for rings with 1 index. - */ -static inline void *mp_ring_current(struct mp_ring *ring) -{ - ASSERT(ring); - ASSERT(ring->pidx == 0); /* not used */ - - return mp_ring_item(ring, ring->cidx); -} - -/* - * Increment index for rings with only 1 index. - * This is used for rings with 1 index. - */ -static inline void *mp_ring_next(struct mp_ring *ring) -{ - ASSERT(ring); - ASSERT(ring->num > 0); - ASSERT(ring->pidx == 0); /* not used */ - - ring->cidx = be_addc(ring->cidx, 1, ring->num); - return mp_ring_current(ring); -} - -/* - This routine waits for a previously posted mailbox WRB to be completed. - Specifically it waits for the mailbox to say that it's ready to accept - more data by setting the LSB of the mailbox pd register to 1. - - pcontroller - The function object to post this data to - - IRQL < DISPATCH_LEVEL -*/ -static void be_mcc_mailbox_wait(struct be_function_object *pfob) -{ - struct MPU_MAILBOX_DB_AMAP mailbox_db; - u32 i = 0; - u32 ready; - - if (pfob->emulate) { - /* No waiting for mailbox in emulated mode. */ - return; - } - - mailbox_db.dw[0] = PD_READ(pfob, mcc_bootstrap_db); - ready = AMAP_GET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db); - - while (ready == false) { - if ((++i & 0x3FFFF) == 0) { - TRACE(DL_WARN, "Waiting for mailbox ready - %dk polls", - i / 1000); - } - udelay(1); - mailbox_db.dw[0] = PD_READ(pfob, mcc_bootstrap_db); - ready = AMAP_GET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db); - } -} - -/* - This routine tells the MCC mailbox that there is data to processed - in the mailbox. It does this by setting the physical address for the - mailbox location and clearing the LSB. This routine returns immediately - and does not wait for the WRB to be processed. - - pcontroller - The function object to post this data to - - IRQL < DISPATCH_LEVEL - -*/ -static void be_mcc_mailbox_notify(struct be_function_object *pfob) -{ - struct MPU_MAILBOX_DB_AMAP mailbox_db; - u32 pa; - - ASSERT(pfob->mailbox.pa); - ASSERT(pfob->mailbox.va); - - /* If emulated, do not ring the mailbox */ - if (pfob->emulate) { - TRACE(DL_WARN, "MPU disabled. Skipping mailbox notify."); - return; - } - - /* form the higher bits in the address */ - mailbox_db.dw[0] = 0; /* init */ - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, hi, &mailbox_db, 1); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db, 0); - - /* bits 34 to 63 */ - pa = (u32) (pfob->mailbox.pa >> 34); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, address, &mailbox_db, pa); - - /* Wait for the MPU to be ready */ - be_mcc_mailbox_wait(pfob); - - /* Ring doorbell 1st time */ - PD_WRITE(pfob, mcc_bootstrap_db, mailbox_db.dw[0]); - - /* Wait for 1st write to be acknowledged. */ - be_mcc_mailbox_wait(pfob); - - /* lower bits 30 bits from 4th bit (bits 4 to 33)*/ - pa = (u32) (pfob->mailbox.pa >> 4) & 0x3FFFFFFF; - - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, hi, &mailbox_db, 0); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db, 0); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, address, &mailbox_db, pa); - - /* Ring doorbell 2nd time */ - PD_WRITE(pfob, mcc_bootstrap_db, mailbox_db.dw[0]); -} - -/* - This routine tells the MCC mailbox that there is data to processed - in the mailbox. It does this by setting the physical address for the - mailbox location and clearing the LSB. This routine spins until the - MPU writes a 1 into the LSB indicating that the data has been received - and is ready to be processed. - - pcontroller - The function object to post this data to - - IRQL < DISPATCH_LEVEL -*/ -static void -be_mcc_mailbox_notify_and_wait(struct be_function_object *pfob) -{ - /* - * Notify it - */ - be_mcc_mailbox_notify(pfob); - /* - * Now wait for completion of WRB - */ - be_mcc_mailbox_wait(pfob); -} - -void -be_mcc_process_cqe(struct be_function_object *pfob, - struct MCC_CQ_ENTRY_AMAP *cqe) -{ - struct be_mcc_wrb_context *wrb_context = NULL; - u32 offset, status; - u8 *p; - - ASSERT(cqe); - /* - * A command completed. Commands complete out-of-order. - * Determine which command completed from the TAG. - */ - offset = offsetof(struct BE_MCC_CQ_ENTRY_AMAP, mcc_tag)/8; - p = (u8 *) cqe + offset; - wrb_context = (struct be_mcc_wrb_context *)(void *)(size_t)(*(u64 *)p); - ASSERT(wrb_context); - - /* - * Perform a response copy if requested. - * Only copy data if the FWCMD is successful. - */ - status = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, completion_status, cqe); - if (status == MGMT_STATUS_SUCCESS && wrb_context->copy.length > 0) { - ASSERT(wrb_context->wrb); - ASSERT(wrb_context->copy.va); - p = (u8 *)wrb_context->wrb + - offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - memcpy(wrb_context->copy.va, - (u8 *)p + wrb_context->copy.fwcmd_offset, - wrb_context->copy.length); - } - - if (status) - status = BE_NOT_OK; - /* internal callback */ - if (wrb_context->internal_cb) { - wrb_context->internal_cb(wrb_context->internal_cb_context, - status, wrb_context->wrb); - } - - /* callback */ - if (wrb_context->cb) { - wrb_context->cb(wrb_context->cb_context, - status, wrb_context->wrb); - } - /* Free the context structure */ - _be_mcc_free_wrb_context(pfob, wrb_context); -} - -void be_drive_mcc_wrb_queue(struct be_mcc_object *mcc) -{ - struct be_function_object *pfob = NULL; - int status = BE_PENDING; - struct be_generic_q_ctxt *q_ctxt; - struct MCC_WRB_AMAP *wrb; - struct MCC_WRB_AMAP *queue_wrb; - u32 length, payload_length, sge_count, embedded; - unsigned long irql; - - BUILD_BUG_ON((sizeof(struct be_generic_q_ctxt) < - sizeof(struct be_queue_driver_context) + - sizeof(struct MCC_WRB_AMAP))); - pfob = mcc->parent_function; - - spin_lock_irqsave(&pfob->post_lock, irql); - - if (mcc->driving_backlog) { - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return; - } - /* Acquire the flag to limit 1 thread to redrive posts. */ - mcc->driving_backlog = 1; - - while (!list_empty(&mcc->backlog)) { - wrb = _be_mpu_peek_ring_wrb(mcc, true); /* Driving the queue */ - if (!wrb) - break; /* No space in the ring yet. */ - /* Get the next queued entry to process. */ - q_ctxt = list_first_entry(&mcc->backlog, - struct be_generic_q_ctxt, context.list); - list_del(&q_ctxt->context.list); - pfob->mcc->backlog_length--; - /* - * Compute the required length of the WRB. - * Since the queue element may be smaller than - * the complete WRB, copy only the required number of bytes. - */ - queue_wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, queue_wrb); - if (embedded) { - payload_length = AMAP_GET_BITS_PTR(MCC_WRB, - payload_length, queue_wrb); - length = sizeof(struct be_mcc_wrb_header) + - payload_length; - } else { - sge_count = AMAP_GET_BITS_PTR(MCC_WRB, sge_count, - queue_wrb); - ASSERT(sge_count == 1); /* only 1 frag. */ - length = sizeof(struct be_mcc_wrb_header) + - sge_count * sizeof(struct MCC_SGE_AMAP); - } - - /* - * Truncate the length based on the size of the - * queue element. Some elements that have output parameters - * can be smaller than the payload_length field would - * indicate. We really only need to copy the request - * parameters, not the response. - */ - length = min(length, (u32) (q_ctxt->context.bytes - - offsetof(struct be_generic_q_ctxt, wrb_header))); - - /* Copy the queue element WRB into the ring. */ - memcpy(wrb, &q_ctxt->wrb_header, length); - - /* Post the wrb. This should not fail assuming we have - * enough context structs. */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, - q_ctxt->context.cb, q_ctxt->context.cb_context, - q_ctxt->context.internal_cb, - q_ctxt->context.internal_cb_context, - q_ctxt->context.optional_fwcmd_va, - &q_ctxt->context.copy); - - if (status == BE_SUCCESS) { - /* - * Synchronous completion. Since it was queued, - * we will invoke the callback. - * To the user, this is an asynchronous request. - */ - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - - ASSERT(q_ctxt->context.cb); - - q_ctxt->context.cb( - q_ctxt->context.cb_context, - BE_SUCCESS, NULL); - - spin_lock_irqsave(&pfob->post_lock, irql); - - } else if (status != BE_PENDING) { - /* - * Another resource failed. Should never happen - * if we have sufficient MCC_WRB_CONTEXT structs. - * Return to head of the queue. - */ - TRACE(DL_WARN, "Failed to post a queued WRB. 0x%x", - status); - list_add(&q_ctxt->context.list, &mcc->backlog); - pfob->mcc->backlog_length++; - break; - } - } - - /* Free the flag to limit 1 thread to redrive posts. */ - mcc->driving_backlog = 0; - spin_unlock_irqrestore(&pfob->post_lock, irql); -} - -/* This function asserts that the WRB was consumed in order. */ -#ifdef BE_DEBUG -u32 be_mcc_wrb_consumed_in_order(struct be_mcc_object *mcc, - struct MCC_CQ_ENTRY_AMAP *cqe) -{ - struct be_mcc_wrb_context *wrb_context = NULL; - u32 wrb_index; - u32 wrb_consumed_in_order; - u32 offset; - u8 *p; - - ASSERT(cqe); - /* - * A command completed. Commands complete out-of-order. - * Determine which command completed from the TAG. - */ - offset = offsetof(struct BE_MCC_CQ_ENTRY_AMAP, mcc_tag)/8; - p = (u8 *) cqe + offset; - wrb_context = (struct be_mcc_wrb_context *)(void *)(size_t)(*(u64 *)p); - - ASSERT(wrb_context); - - wrb_index = (u32) (((u64)(size_t)wrb_context->ring_wrb - - (u64)(size_t)mcc->sq.ring.va) / sizeof(struct MCC_WRB_AMAP)); - - ASSERT(wrb_index < mcc->sq.ring.num); - - wrb_consumed_in_order = (u32) (wrb_index == mcc->consumed_index); - mcc->consumed_index = be_addc(mcc->consumed_index, 1, mcc->sq.ring.num); - return wrb_consumed_in_order; -} -#endif - -int be_mcc_process_cq(struct be_mcc_object *mcc, bool rearm) -{ - struct be_function_object *pfob = NULL; - struct MCC_CQ_ENTRY_AMAP *cqe; - struct CQ_DB_AMAP db; - struct mp_ring *cq_ring = &mcc->cq.ring; - struct mp_ring *mp_ring = &mcc->sq.ring; - u32 num_processed = 0; - u32 consumed = 0, valid, completed, cqe_consumed, async_event; - - pfob = mcc->parent_function; - - spin_lock_irqsave(&pfob->cq_lock, pfob->cq_irq); - - /* - * Verify that only one thread is processing the CQ at once. - * We cannot hold the lock while processing the CQ due to - * the callbacks into the OS. Therefore, this flag is used - * to control it. If any of the threads want to - * rearm the CQ, we need to honor that. - */ - if (mcc->processing != 0) { - mcc->rearm = mcc->rearm || rearm; - goto Error; - } else { - mcc->processing = 1; /* lock processing for this thread. */ - mcc->rearm = rearm; /* set our rearm setting */ - } - - spin_unlock_irqrestore(&pfob->cq_lock, pfob->cq_irq); - - cqe = mp_ring_current(cq_ring); - valid = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe); - while (valid) { - - if (num_processed >= 8) { - /* coalesce doorbells, but free space in cq - * ring while processing. */ - db.dw[0] = 0; /* clear */ - AMAP_SET_BITS_PTR(CQ_DB, qid, &db, cq_ring->id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &db, false); - AMAP_SET_BITS_PTR(CQ_DB, event, &db, false); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &db, - num_processed); - num_processed = 0; - - PD_WRITE(pfob, cq_db, db.dw[0]); - } - - async_event = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, async_event, cqe); - if (async_event) { - /* This is an asynchronous event. */ - struct ASYNC_EVENT_TRAILER_AMAP *async_trailer = - (struct ASYNC_EVENT_TRAILER_AMAP *) - ((u8 *) cqe + sizeof(struct MCC_CQ_ENTRY_AMAP) - - sizeof(struct ASYNC_EVENT_TRAILER_AMAP)); - u32 event_code; - async_event = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, - async_event, async_trailer); - ASSERT(async_event == 1); - - - valid = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, - valid, async_trailer); - ASSERT(valid == 1); - - /* Call the async event handler if it is installed. */ - if (mcc->async_cb) { - event_code = - AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, - event_code, async_trailer); - mcc->async_cb(mcc->async_context, - (u32) event_code, (void *) cqe); - } - - } else { - /* This is a completion entry. */ - - /* No vm forwarding in this driver. */ - - cqe_consumed = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, - consumed, cqe); - if (cqe_consumed) { - /* - * A command on the MCC ring was consumed. - * Update the consumer index. - * These occur in order. - */ - ASSERT(be_mcc_wrb_consumed_in_order(mcc, cqe)); - consumed++; - } - - completed = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, - completed, cqe); - if (completed) { - /* A command completed. Use tag to - * determine which command. */ - be_mcc_process_cqe(pfob, cqe); - } - } - - /* Reset the CQE */ - AMAP_SET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe, false); - num_processed++; - - /* Update our tracking for the CQ ring. */ - cqe = mp_ring_next(cq_ring); - valid = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe); - } - - TRACE(DL_INFO, "num_processed:0x%x, and consumed:0x%x", - num_processed, consumed); - /* - * Grab the CQ lock to synchronize the "rearm" setting for - * the doorbell, and for clearing the "processing" flag. - */ - spin_lock_irqsave(&pfob->cq_lock, pfob->cq_irq); - - /* - * Rearm the cq. This is done based on the global mcc->rearm - * flag which combines the rearm parameter from the current - * call to process_cq and any other threads - * that tried to process the CQ while this one was active. - * This handles the situation where a sync. fwcmd was processing - * the CQ while the interrupt/dpc tries to process it. - * The sync process gets to continue -- but it is now - * responsible for the rearming. - */ - if (num_processed > 0 || mcc->rearm == true) { - db.dw[0] = 0; /* clear */ - AMAP_SET_BITS_PTR(CQ_DB, qid, &db, cq_ring->id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &db, mcc->rearm); - AMAP_SET_BITS_PTR(CQ_DB, event, &db, false); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &db, num_processed); - - PD_WRITE(pfob, cq_db, db.dw[0]); - } - /* - * Update the consumer index after ringing the CQ doorbell. - * We don't want another thread to post more WRBs before we - * have CQ space available. - */ - mp_ring_consume_multiple(mp_ring, consumed); - - /* Clear the processing flag. */ - mcc->processing = 0; - -Error: - spin_unlock_irqrestore(&pfob->cq_lock, pfob->cq_irq); - /* - * Use the local variable to detect if the current thread - * holds the WRB post lock. If rearm is false, this is - * either a synchronous command, or the upper layer driver is polling - * from a thread. We do not drive the queue from that - * context since the driver may hold the - * wrb post lock already. - */ - if (rearm) - be_drive_mcc_wrb_queue(mcc); - else - pfob->pend_queue_driving = 1; - - return BE_SUCCESS; -} - -/* - *============================================================================ - * P U B L I C R O U T I N E S - *============================================================================ - */ - -/* - This routine creates an MCC object. This object contains an MCC send queue - and a CQ private to the MCC. - - pcontroller - Handle to a function object - - EqObject - EQ object that will be used to dispatch this MCC - - ppMccObject - Pointer to an internal Mcc Object returned. - - Returns BE_SUCCESS if successfull,, otherwise a useful error code - is returned. - - IRQL < DISPATCH_LEVEL - -*/ -int -be_mcc_ring_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, - struct be_mcc_wrb_context *context_array, - u32 num_context_entries, - struct be_cq_object *cq, struct be_mcc_object *mcc) -{ - int status = 0; - - struct FWCMD_COMMON_MCC_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - u32 num_entries_encoded, n, i; - void *va = NULL; - unsigned long irql; - - if (length < sizeof(struct MCC_WRB_AMAP) * 2) { - TRACE(DL_ERR, "Invalid MCC ring length:%d", length); - return BE_NOT_OK; - } - /* - * Reduce the actual ring size to be less than the number - * of context entries. This ensures that we run out of - * ring WRBs first so the queuing works correctly. We never - * queue based on context structs. - */ - if (num_context_entries + 1 < - length / sizeof(struct MCC_WRB_AMAP) - 1) { - - u32 max_length = - (num_context_entries + 2) * sizeof(struct MCC_WRB_AMAP); - - if (is_power_of_2(max_length)) - length = __roundup_pow_of_two(max_length+1) / 2; - else - length = __roundup_pow_of_two(max_length) / 2; - - ASSERT(length <= max_length); - - TRACE(DL_WARN, - "MCC ring length reduced based on context entries." - " length:%d wrbs:%d context_entries:%d", length, - (int) (length / sizeof(struct MCC_WRB_AMAP)), - num_context_entries); - } - - spin_lock_irqsave(&pfob->post_lock, irql); - - num_entries_encoded = - be_ring_length_to_encoding(length, sizeof(struct MCC_WRB_AMAP)); - - /* Init MCC object. */ - memset(mcc, 0, sizeof(*mcc)); - mcc->parent_function = pfob; - mcc->cq_object = cq; - - INIT_LIST_HEAD(&mcc->backlog); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_MCC_CREATE); - - fwcmd->params.request.num_pages = DIV_ROUND_UP(length, PAGE_SIZE); - /* - * Program MCC ring context - */ - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, pdid, - &fwcmd->params.request.context, 0); - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, invalid, - &fwcmd->params.request.context, false); - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, ring_size, - &fwcmd->params.request.context, num_entries_encoded); - - n = cq->cq_id; - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, - cq_id, &fwcmd->params.request.context, n); - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create CQ failed."); - goto error; - } - /* - * Create a linked list of context structures - */ - mcc->wrb_context.base = context_array; - mcc->wrb_context.num = num_context_entries; - INIT_LIST_HEAD(&mcc->wrb_context.list_head); - memset(context_array, 0, - sizeof(struct be_mcc_wrb_context) * num_context_entries); - for (i = 0; i < mcc->wrb_context.num; i++) { - list_add_tail(&context_array[i].next, - &mcc->wrb_context.list_head); - } - - /* - * - * Create an mcc_ring for tracking WRB hw ring - */ - va = rd->va; - ASSERT(va); - mp_ring_create(&mcc->sq.ring, length / sizeof(struct MCC_WRB_AMAP), - sizeof(struct MCC_WRB_AMAP), va); - mcc->sq.ring.id = fwcmd->params.response.id; - /* - * Init a mcc_ring for tracking the MCC CQ. - */ - ASSERT(cq->va); - mp_ring_create(&mcc->cq.ring, cq->num_entries, - sizeof(struct MCC_CQ_ENTRY_AMAP), cq->va); - mcc->cq.ring.id = cq->cq_id; - - /* Force zeroing of CQ. */ - memset(cq->va, 0, cq->num_entries * sizeof(struct MCC_CQ_ENTRY_AMAP)); - - /* Initialize debug index. */ - mcc->consumed_index = 0; - - atomic_inc(&cq->ref_count); - pfob->mcc = mcc; - - TRACE(DL_INFO, "MCC ring created. id:%d bytes:%d cq_id:%d cq_entries:%d" - " num_context:%d", mcc->sq.ring.id, length, - cq->cq_id, cq->num_entries, num_context_entries); - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine destroys an MCC send queue - - MccObject - Internal Mcc Object to be destroyed. - - Returns BE_SUCCESS if successfull, otherwise an error code is returned. - - IRQL < DISPATCH_LEVEL - - The caller of this routine must ensure that no other WRB may be posted - until this routine returns. - -*/ -int be_mcc_ring_destroy(struct be_mcc_object *mcc) -{ - int status = 0; - struct be_function_object *pfob = mcc->parent_function; - - - ASSERT(mcc->processing == 0); - - /* - * Remove the ring from the function object. - * This transitions back to mailbox mode. - */ - pfob->mcc = NULL; - - /* Send fwcmd to destroy the queue. (Using the mailbox.) */ - status = be_function_ring_destroy(mcc->parent_function, mcc->sq.ring.id, - FWCMD_RING_TYPE_MCC, NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - /* Release the SQ reference to the CQ */ - atomic_dec(&mcc->cq_object->ref_count); - - return status; -} - -static void -mcc_wrb_sync_cb(void *context, int staus, struct MCC_WRB_AMAP *wrb) -{ - struct be_mcc_wrb_context *wrb_context = - (struct be_mcc_wrb_context *) context; - ASSERT(wrb_context); - *wrb_context->users_final_status = staus; -} - -/* - This routine posts a command to the MCC send queue - - mcc - Internal Mcc Object to be destroyed. - - wrb - wrb to post. - - Returns BE_SUCCESS if successfull, otherwise an error code is returned. - - IRQL < DISPATCH_LEVEL if CompletionCallback is not NULL - IRQL <=DISPATCH_LEVEL if CompletionCallback is NULL - - If this routine is called with CompletionCallback != NULL the - call is considered to be asynchronous and will return as soon - as the WRB is posted to the MCC with BE_PENDING. - - If CompletionCallback is NULL, then this routine will not return until - a completion for this MCC command has been processed. - If called at DISPATCH_LEVEL the CompletionCallback must be NULL. - - This routine should only be called if the MPU has been boostraped past - mailbox mode. - - -*/ -int -_be_mpu_post_wrb_ring(struct be_mcc_object *mcc, struct MCC_WRB_AMAP *wrb, - struct be_mcc_wrb_context *wrb_context) -{ - - struct MCC_WRB_AMAP *ring_wrb = NULL; - int status = BE_PENDING; - int final_status = BE_PENDING; - mcc_wrb_cqe_callback cb = NULL; - struct MCC_DB_AMAP mcc_db; - u32 embedded; - - ASSERT(mp_ring_num_empty(&mcc->sq.ring) > 0); - /* - * Input wrb is most likely the next wrb in the ring, since the client - * can peek at the address. - */ - ring_wrb = mp_ring_producer_ptr(&mcc->sq.ring); - if (wrb != ring_wrb) { - /* If not equal, copy it into the ring. */ - memcpy(ring_wrb, wrb, sizeof(struct MCC_WRB_AMAP)); - } -#ifdef BE_DEBUG - wrb_context->ring_wrb = ring_wrb; -#endif - embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, ring_wrb); - if (embedded) { - /* embedded commands will have the response within the WRB. */ - wrb_context->wrb = ring_wrb; - } else { - /* - * non-embedded commands will not have the response - * within the WRB, and they may complete out-of-order. - * The WRB will not be valid to inspect - * during the completion. - */ - wrb_context->wrb = NULL; - } - cb = wrb_context->cb; - - if (cb == NULL) { - /* Assign our internal callback if this is a - * synchronous call. */ - wrb_context->cb = mcc_wrb_sync_cb; - wrb_context->cb_context = wrb_context; - wrb_context->users_final_status = &final_status; - } - /* Increment producer index */ - - mcc_db.dw[0] = 0; /* initialize */ - AMAP_SET_BITS_PTR(MCC_DB, rid, &mcc_db, mcc->sq.ring.id); - AMAP_SET_BITS_PTR(MCC_DB, numPosted, &mcc_db, 1); - - mp_ring_produce(&mcc->sq.ring); - PD_WRITE(mcc->parent_function, mpu_mcc_db, mcc_db.dw[0]); - TRACE(DL_INFO, "pidx: %x and cidx: %x.", mcc->sq.ring.pidx, - mcc->sq.ring.cidx); - - if (cb == NULL) { - int polls = 0; /* At >= 1 us per poll */ - /* Wait until this command completes, polling the CQ. */ - do { - TRACE(DL_INFO, "FWCMD submitted in the poll mode."); - /* Do not rearm CQ in this context. */ - be_mcc_process_cq(mcc, false); - - if (final_status == BE_PENDING) { - if ((++polls & 0x7FFFF) == 0) { - TRACE(DL_WARN, - "Warning : polling MCC CQ for %d" - "ms.", polls / 1000); - } - - udelay(1); - } - - /* final_status changed when the command completes */ - } while (final_status == BE_PENDING); - - status = final_status; - } - - return status; -} - -struct MCC_WRB_AMAP * -_be_mpu_peek_ring_wrb(struct be_mcc_object *mcc, bool driving_queue) -{ - /* If we have queued items, do not allow a post to bypass the queue. */ - if (!driving_queue && !list_empty(&mcc->backlog)) - return NULL; - - if (mp_ring_num_empty(&mcc->sq.ring) <= 0) - return NULL; - return (struct MCC_WRB_AMAP *) mp_ring_producer_ptr(&mcc->sq.ring); -} - -int -be_mpu_init_mailbox(struct be_function_object *pfob, struct ring_desc *mailbox) -{ - ASSERT(mailbox); - pfob->mailbox.va = mailbox->va; - pfob->mailbox.pa = cpu_to_le64(mailbox->pa); - pfob->mailbox.length = mailbox->length; - - ASSERT(((u32)(size_t)pfob->mailbox.va & 0xf) == 0); - ASSERT(((u32)(size_t)pfob->mailbox.pa & 0xf) == 0); - /* - * Issue the WRB to set MPU endianness - */ - { - u64 *endian_check = (u64 *) (pfob->mailbox.va + - offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8); - *endian_check = 0xFF1234FFFF5678FFULL; - } - - be_mcc_mailbox_notify_and_wait(pfob); - - return BE_SUCCESS; -} - - -/* - This routine posts a command to the MCC mailbox. - - FuncObj - Function Object to post the WRB on behalf of. - wrb - wrb to post. - CompletionCallback - Address of a callback routine to invoke once the WRB - is completed. - CompletionCallbackContext - Opaque context to be passed during the call to - the CompletionCallback. - Returns BE_SUCCESS if successfull, otherwise an error code is returned. - - IRQL <=DISPATCH_LEVEL if CompletionCallback is NULL - - This routine will block until a completion for this MCC command has been - processed. If called at DISPATCH_LEVEL the CompletionCallback must be NULL. - - This routine should only be called if the MPU has not been boostraped past - mailbox mode. -*/ -int -_be_mpu_post_wrb_mailbox(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context) -{ - struct MCC_MAILBOX_AMAP *mailbox = NULL; - struct MCC_WRB_AMAP *mb_wrb; - struct MCC_CQ_ENTRY_AMAP *mb_cq; - u32 offset, status; - - ASSERT(pfob->mcc == NULL); - mailbox = pfob->mailbox.va; - ASSERT(mailbox); - - offset = offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8; - mb_wrb = (struct MCC_WRB_AMAP *) (u8 *)mailbox + offset; - if (mb_wrb != wrb) { - memset(mailbox, 0, sizeof(*mailbox)); - memcpy(mb_wrb, wrb, sizeof(struct MCC_WRB_AMAP)); - } - /* The callback can inspect the final WRB to get output parameters. */ - wrb_context->wrb = mb_wrb; - - be_mcc_mailbox_notify_and_wait(pfob); - - /* A command completed. Use tag to determine which command. */ - offset = offsetof(struct BE_MCC_MAILBOX_AMAP, cq)/8; - mb_cq = (struct MCC_CQ_ENTRY_AMAP *) ((u8 *)mailbox + offset); - be_mcc_process_cqe(pfob, mb_cq); - - status = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, completion_status, mb_cq); - if (status) - status = BE_NOT_OK; - return status; -} - -struct be_mcc_wrb_context * -_be_mcc_allocate_wrb_context(struct be_function_object *pfob) -{ - struct be_mcc_wrb_context *context = NULL; - unsigned long irq; - - spin_lock_irqsave(&pfob->mcc_context_lock, irq); - - if (!pfob->mailbox.default_context_allocated) { - /* Use the single default context that we - * always have allocated. */ - pfob->mailbox.default_context_allocated = true; - context = &pfob->mailbox.default_context; - } else if (pfob->mcc) { - /* Get a context from the free list. If any are available. */ - if (!list_empty(&pfob->mcc->wrb_context.list_head)) { - context = list_first_entry( - &pfob->mcc->wrb_context.list_head, - struct be_mcc_wrb_context, next); - } - } - - spin_unlock_irqrestore(&pfob->mcc_context_lock, irq); - - return context; -} - -void -_be_mcc_free_wrb_context(struct be_function_object *pfob, - struct be_mcc_wrb_context *context) -{ - unsigned long irq; - - ASSERT(context); - /* - * Zero during free to try and catch any bugs where the context - * is accessed after a free. - */ - memset(context, 0, sizeof(context)); - - spin_lock_irqsave(&pfob->mcc_context_lock, irq); - - if (context == &pfob->mailbox.default_context) { - /* Free the default context. */ - ASSERT(pfob->mailbox.default_context_allocated); - pfob->mailbox.default_context_allocated = false; - } else { - /* Add to free list. */ - ASSERT(pfob->mcc); - list_add_tail(&context->next, - &pfob->mcc->wrb_context.list_head); - } - - spin_unlock_irqrestore(&pfob->mcc_context_lock, irq); -} - -int -be_mcc_add_async_event_callback(struct be_mcc_object *mcc_object, - mcc_async_event_callback cb, void *cb_context) -{ - /* Lock against anyone trying to change the callback/context pointers - * while being used. */ - spin_lock_irqsave(&mcc_object->parent_function->cq_lock, - mcc_object->parent_function->cq_irq); - - /* Assign the async callback. */ - mcc_object->async_context = cb_context; - mcc_object->async_cb = cb; - - spin_unlock_irqrestore(&mcc_object->parent_function->cq_lock, - mcc_object->parent_function->cq_irq); - - return BE_SUCCESS; -} - -#define MPU_EP_CONTROL 0 -#define MPU_EP_SEMAPHORE 0xac - -/* - *------------------------------------------------------------------- - * Function: be_wait_for_POST_complete - * Waits until the BladeEngine POST completes (either in error or success). - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -static int be_wait_for_POST_complete(struct be_function_object *pfob) -{ - struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status; - int s; - u32 post_error, post_stage; - - const u32 us_per_loop = 1000; /* 1000us */ - const u32 print_frequency_loops = 1000000 / us_per_loop; - const u32 max_loops = 60 * print_frequency_loops; - u32 loops = 0; - - /* - * Wait for arm fw indicating it is done or a fatal error happened. - * Note: POST can take some time to complete depending on configuration - * settings (consider ARM attempts to acquire an IP address - * over DHCP!!!). - * - */ - do { - status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE); - post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - error, &status); - post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - stage, &status); - if (0 == (loops % print_frequency_loops)) { - /* Print current status */ - TRACE(DL_INFO, "POST status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - } - udelay(us_per_loop); - } while ((post_error != 1) && - (post_stage != POST_STAGE_ARMFW_READY) && - (++loops < max_loops)); - - if (post_error == 1) { - TRACE(DL_ERR, "POST error! Status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - s = BE_NOT_OK; - } else if (post_stage != POST_STAGE_ARMFW_READY) { - TRACE(DL_ERR, "POST time-out! Status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - s = BE_NOT_OK; - } else { - s = BE_SUCCESS; - } - return s; -} - -/* - *------------------------------------------------------------------- - * Function: be_kickoff_and_wait_for_POST - * Interacts with the BladeEngine management processor to initiate POST, and - * subsequently waits until POST completes (either in error or success). - * The caller must acquire the reset semaphore before initiating POST - * to prevent multiple drivers interacting with the management processor. - * Once POST is complete the caller must release the reset semaphore. - * Callers who only want to wait for POST complete may call - * be_wait_for_POST_complete. - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -static int -be_kickoff_and_wait_for_POST(struct be_function_object *pfob) -{ - struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status; - int s; - - const u32 us_per_loop = 1000; /* 1000us */ - const u32 print_frequency_loops = 1000000 / us_per_loop; - const u32 max_loops = 5 * print_frequency_loops; - u32 loops = 0; - u32 post_error, post_stage; - - /* Wait for arm fw awaiting host ready or a fatal error happened. */ - TRACE(DL_INFO, "Wait for BladeEngine ready to POST"); - do { - status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE); - post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - error, &status); - post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - stage, &status); - if (0 == (loops % print_frequency_loops)) { - /* Print current status */ - TRACE(DL_INFO, "POST status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - } - udelay(us_per_loop); - } while ((post_error != 1) && - (post_stage < POST_STAGE_AWAITING_HOST_RDY) && - (++loops < max_loops)); - - if (post_error == 1) { - TRACE(DL_ERR, "Pre-POST error! Status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - s = BE_NOT_OK; - } else if (post_stage == POST_STAGE_AWAITING_HOST_RDY) { - iowrite32(POST_STAGE_HOST_RDY, pfob->csr_va + MPU_EP_SEMAPHORE); - - /* Wait for POST to complete */ - s = be_wait_for_POST_complete(pfob); - } else { - /* - * Either a timeout waiting for host ready signal or POST has - * moved ahead without requiring a host ready signal. - * Might as well give POST a chance to complete - * (or timeout again). - */ - s = be_wait_for_POST_complete(pfob); - } - return s; -} - -/* - *------------------------------------------------------------------- - * Function: be_pci_soft_reset - * This function is called to issue a BladeEngine soft reset. - * Callers should acquire the soft reset semaphore before calling this - * function. Additionaly, callers should ensure they cannot be pre-empted - * while the routine executes. Upon completion of this routine, callers - * should release the reset semaphore. This routine implicitly waits - * for BladeEngine POST to complete. - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -int be_pci_soft_reset(struct be_function_object *pfob) -{ - struct PCICFG_SOFT_RESET_CSR_AMAP soft_reset; - struct PCICFG_ONLINE0_CSR_AMAP pciOnline0; - struct PCICFG_ONLINE1_CSR_AMAP pciOnline1; - struct EP_CONTROL_CSR_AMAP epControlCsr; - int status = BE_SUCCESS; - u32 i, soft_reset_bit; - - TRACE(DL_NOTE, "PCI reset..."); - - /* Issue soft reset #1 to get BladeEngine into a known state. */ - soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset); - AMAP_SET_BITS_PTR(PCICFG_SOFT_RESET_CSR, softreset, soft_reset.dw, 1); - PCICFG0_WRITE(pfob, host_timer_int_ctrl, soft_reset.dw[0]); - /* - * wait til soft reset is deasserted - hardware - * deasserts after some time. - */ - i = 0; - do { - udelay(50); - soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset); - soft_reset_bit = AMAP_GET_BITS_PTR(PCICFG_SOFT_RESET_CSR, - softreset, soft_reset.dw); - } while (soft_reset_bit && (i++ < 1024)); - if (soft_reset_bit != 0) { - TRACE(DL_ERR, "Soft-reset #1 did not deassert as expected."); - status = BE_NOT_OK; - goto Error_label; - } - /* Mask everything */ - PCICFG0_WRITE(pfob, ue_status_low_mask, 0xFFFFFFFF); - PCICFG0_WRITE(pfob, ue_status_hi_mask, 0xFFFFFFFF); - /* - * Set everything offline except MPU IRAM (it is offline with - * the soft-reset, but soft-reset does not reset the PCICFG registers!) - */ - pciOnline0.dw[0] = 0; - pciOnline1.dw[0] = 0; - AMAP_SET_BITS_PTR(PCICFG_ONLINE1_CSR, mpu_iram_online, - pciOnline1.dw, 1); - PCICFG0_WRITE(pfob, online0, pciOnline0.dw[0]); - PCICFG0_WRITE(pfob, online1, pciOnline1.dw[0]); - - udelay(20000); - - /* Issue soft reset #2. */ - AMAP_SET_BITS_PTR(PCICFG_SOFT_RESET_CSR, softreset, soft_reset.dw, 1); - PCICFG0_WRITE(pfob, host_timer_int_ctrl, soft_reset.dw[0]); - /* - * wait til soft reset is deasserted - hardware - * deasserts after some time. - */ - i = 0; - do { - udelay(50); - soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset); - soft_reset_bit = AMAP_GET_BITS_PTR(PCICFG_SOFT_RESET_CSR, - softreset, soft_reset.dw); - } while (soft_reset_bit && (i++ < 1024)); - if (soft_reset_bit != 0) { - TRACE(DL_ERR, "Soft-reset #1 did not deassert as expected."); - status = BE_NOT_OK; - goto Error_label; - } - - - udelay(20000); - - /* Take MPU out of reset. */ - - epControlCsr.dw[0] = ioread32(pfob->csr_va + MPU_EP_CONTROL); - AMAP_SET_BITS_PTR(EP_CONTROL_CSR, CPU_reset, &epControlCsr, 0); - iowrite32((u32)epControlCsr.dw[0], pfob->csr_va + MPU_EP_CONTROL); - - /* Kickoff BE POST and wait for completion */ - status = be_kickoff_and_wait_for_POST(pfob); - -Error_label: - return status; -} - - -/* - *------------------------------------------------------------------- - * Function: be_pci_reset_required - * This private function is called to detect if a host entity is - * required to issue a PCI soft reset and subsequently drive - * BladeEngine POST. Scenarios where this is required: - * 1) BIOS-less configuration - * 2) Hot-swap/plug/power-on - * pfob - - * return true if a reset is required, false otherwise - *------------------------------------------------------------------- - */ -static bool be_pci_reset_required(struct be_function_object *pfob) -{ - struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status; - bool do_reset = false; - u32 post_error, post_stage; - - /* - * Read the POST status register - */ - status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE); - post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, error, - &status); - post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, stage, - &status); - if (post_stage <= POST_STAGE_AWAITING_HOST_RDY) { - /* - * If BladeEngine is waiting for host ready indication, - * we want to do a PCI reset. - */ - do_reset = true; - } - - return do_reset; -} - -/* - *------------------------------------------------------------------- - * Function: be_drive_POST - * This function is called to drive BladeEngine POST. The - * caller should ensure they cannot be pre-empted while this routine executes. - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -int be_drive_POST(struct be_function_object *pfob) -{ - int status; - - if (false != be_pci_reset_required(pfob)) { - /* PCI reset is needed (implicitly starts and waits for POST) */ - status = be_pci_soft_reset(pfob); - } else { - /* No PCI reset is needed, start POST */ - status = be_kickoff_and_wait_for_POST(pfob); - } - - return status; -} diff --git a/drivers/staging/benet/mpu.h b/drivers/staging/benet/mpu.h deleted file mode 100644 index 41f3f87516e5..000000000000 --- a/drivers/staging/benet/mpu.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __mpu_amap_h__ -#define __mpu_amap_h__ -#include "ep.h" - -/* Provide control parameters for the Managment Processor Unit. */ -struct BE_MPU_CSRMAP_AMAP { - struct BE_EP_CSRMAP_AMAP ep; - u8 rsvd0[128]; /* DWORD 64 */ - u8 rsvd1[32]; /* DWORD 68 */ - u8 rsvd2[192]; /* DWORD 69 */ - u8 rsvd3[192]; /* DWORD 75 */ - u8 rsvd4[32]; /* DWORD 81 */ - u8 rsvd5[32]; /* DWORD 82 */ - u8 rsvd6[32]; /* DWORD 83 */ - u8 rsvd7[32]; /* DWORD 84 */ - u8 rsvd8[32]; /* DWORD 85 */ - u8 rsvd9[32]; /* DWORD 86 */ - u8 rsvd10[32]; /* DWORD 87 */ - u8 rsvd11[32]; /* DWORD 88 */ - u8 rsvd12[32]; /* DWORD 89 */ - u8 rsvd13[32]; /* DWORD 90 */ - u8 rsvd14[32]; /* DWORD 91 */ - u8 rsvd15[32]; /* DWORD 92 */ - u8 rsvd16[32]; /* DWORD 93 */ - u8 rsvd17[32]; /* DWORD 94 */ - u8 rsvd18[32]; /* DWORD 95 */ - u8 rsvd19[32]; /* DWORD 96 */ - u8 rsvd20[32]; /* DWORD 97 */ - u8 rsvd21[32]; /* DWORD 98 */ - u8 rsvd22[32]; /* DWORD 99 */ - u8 rsvd23[32]; /* DWORD 100 */ - u8 rsvd24[32]; /* DWORD 101 */ - u8 rsvd25[32]; /* DWORD 102 */ - u8 rsvd26[32]; /* DWORD 103 */ - u8 rsvd27[32]; /* DWORD 104 */ - u8 rsvd28[96]; /* DWORD 105 */ - u8 rsvd29[32]; /* DWORD 108 */ - u8 rsvd30[32]; /* DWORD 109 */ - u8 rsvd31[32]; /* DWORD 110 */ - u8 rsvd32[32]; /* DWORD 111 */ - u8 rsvd33[32]; /* DWORD 112 */ - u8 rsvd34[96]; /* DWORD 113 */ - u8 rsvd35[32]; /* DWORD 116 */ - u8 rsvd36[32]; /* DWORD 117 */ - u8 rsvd37[32]; /* DWORD 118 */ - u8 rsvd38[32]; /* DWORD 119 */ - u8 rsvd39[32]; /* DWORD 120 */ - u8 rsvd40[32]; /* DWORD 121 */ - u8 rsvd41[134][32]; /* DWORD 122 */ -} __packed; -struct MPU_CSRMAP_AMAP { - u32 dw[256]; -}; - -#endif /* __mpu_amap_h__ */ diff --git a/drivers/staging/benet/mpu_context.h b/drivers/staging/benet/mpu_context.h deleted file mode 100644 index 8ce90f9c46c2..000000000000 --- a/drivers/staging/benet/mpu_context.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __mpu_context_amap_h__ -#define __mpu_context_amap_h__ - -/* - * Management command and control ring context. The MPUs BTLR_CTRL1 CSR - * controls the writeback behavior of the producer and consumer index values. - */ -struct BE_MCC_RING_CONTEXT_AMAP { - u8 con_index[16]; /* DWORD 0 */ - u8 ring_size[4]; /* DWORD 0 */ - u8 cq_id[11]; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 prod_index[16]; /* DWORD 1 */ - u8 pdid[15]; /* DWORD 1 */ - u8 invalid; /* DWORD 1 */ - u8 cmd_pending_current[7]; /* DWORD 2 */ - u8 rsvd1[25]; /* DWORD 2 */ - u8 hpi_port_cq_id[11]; /* DWORD 3 */ - u8 rsvd2[5]; /* DWORD 3 */ - u8 cmd_pending_max[7]; /* DWORD 3 */ - u8 rsvd3[9]; /* DWORD 3 */ -} __packed; -struct MCC_RING_CONTEXT_AMAP { - u32 dw[4]; -}; - -#endif /* __mpu_context_amap_h__ */ diff --git a/drivers/staging/benet/pcicfg.h b/drivers/staging/benet/pcicfg.h deleted file mode 100644 index 7c15684adf4a..000000000000 --- a/drivers/staging/benet/pcicfg.h +++ /dev/null @@ -1,825 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __pcicfg_amap_h__ -#define __pcicfg_amap_h__ - -/* Vendor and Device ID Register. */ -struct BE_PCICFG_ID_CSR_AMAP { - u8 vendorid[16]; /* DWORD 0 */ - u8 deviceid[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_ID_CSR_AMAP { - u32 dw[1]; -}; - -/* IO Bar Register. */ -struct BE_PCICFG_IOBAR_CSR_AMAP { - u8 iospace; /* DWORD 0 */ - u8 rsvd0[7]; /* DWORD 0 */ - u8 iobar[24]; /* DWORD 0 */ -} __packed; -struct PCICFG_IOBAR_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 0 Register. */ -struct BE_PCICFG_MEMBAR0_CSR_AMAP { - u8 memspace; /* DWORD 0 */ - u8 type[2]; /* DWORD 0 */ - u8 pf; /* DWORD 0 */ - u8 rsvd0[10]; /* DWORD 0 */ - u8 membar0[18]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR0_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 1 - Low Address Register. */ -struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP { - u8 memspace; /* DWORD 0 */ - u8 type[2]; /* DWORD 0 */ - u8 pf; /* DWORD 0 */ - u8 rsvd0[13]; /* DWORD 0 */ - u8 membar1lo[15]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR1_LO_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 1 - High Address Register. */ -struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP { - u8 membar1hi[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR1_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 2 - Low Address Register. */ -struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP { - u8 memspace; /* DWORD 0 */ - u8 type[2]; /* DWORD 0 */ - u8 pf; /* DWORD 0 */ - u8 rsvd0[17]; /* DWORD 0 */ - u8 membar2lo[11]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR2_LO_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 2 - High Address Register. */ -struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP { - u8 membar2hi[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR2_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* Subsystem Vendor and ID (Function 0) Register. */ -struct BE_PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP { - u8 subsys_vendor_id[16]; /* DWORD 0 */ - u8 subsys_id[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP { - u32 dw[1]; -}; - -/* Subsystem Vendor and ID (Function 1) Register. */ -struct BE_PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP { - u8 subsys_vendor_id[16]; /* DWORD 0 */ - u8 subsys_id[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP { - u32 dw[1]; -}; - -/* Semaphore Register. */ -struct BE_PCICFG_SEMAPHORE_CSR_AMAP { - u8 locked; /* DWORD 0 */ - u8 rsvd0[31]; /* DWORD 0 */ -} __packed; -struct PCICFG_SEMAPHORE_CSR_AMAP { - u32 dw[1]; -}; - -/* Soft Reset Register. */ -struct BE_PCICFG_SOFT_RESET_CSR_AMAP { - u8 rsvd0[7]; /* DWORD 0 */ - u8 softreset; /* DWORD 0 */ - u8 rsvd1[16]; /* DWORD 0 */ - u8 nec_ll_rcvdetect_i[8]; /* DWORD 0 */ -} __packed; -struct PCICFG_SOFT_RESET_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Status (Low) Register. Each bit corresponds to - * an internal Unrecoverable Error. These are set by hardware and may be - * cleared by writing a one to the respective bit(s) to be cleared. Any - * bit being set that is also unmasked will result in Unrecoverable Error - * interrupt notification to the host CPU and/or Server Management chip - * and the transitioning of BladeEngine to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP { - u8 cev_ue_status; /* DWORD 0 */ - u8 ctx_ue_status; /* DWORD 0 */ - u8 dbuf_ue_status; /* DWORD 0 */ - u8 erx_ue_status; /* DWORD 0 */ - u8 host_ue_status; /* DWORD 0 */ - u8 mpu_ue_status; /* DWORD 0 */ - u8 ndma_ue_status; /* DWORD 0 */ - u8 ptc_ue_status; /* DWORD 0 */ - u8 rdma_ue_status; /* DWORD 0 */ - u8 rxf_ue_status; /* DWORD 0 */ - u8 rxips_ue_status; /* DWORD 0 */ - u8 rxulp0_ue_status; /* DWORD 0 */ - u8 rxulp1_ue_status; /* DWORD 0 */ - u8 rxulp2_ue_status; /* DWORD 0 */ - u8 tim_ue_status; /* DWORD 0 */ - u8 tpost_ue_status; /* DWORD 0 */ - u8 tpre_ue_status; /* DWORD 0 */ - u8 txips_ue_status; /* DWORD 0 */ - u8 txulp0_ue_status; /* DWORD 0 */ - u8 txulp1_ue_status; /* DWORD 0 */ - u8 uc_ue_status; /* DWORD 0 */ - u8 wdma_ue_status; /* DWORD 0 */ - u8 txulp2_ue_status; /* DWORD 0 */ - u8 host1_ue_status; /* DWORD 0 */ - u8 p0_ob_link_ue_status; /* DWORD 0 */ - u8 p1_ob_link_ue_status; /* DWORD 0 */ - u8 host_gpio_ue_status; /* DWORD 0 */ - u8 mbox_netw_ue_status; /* DWORD 0 */ - u8 mbox_stor_ue_status; /* DWORD 0 */ - u8 axgmac0_ue_status; /* DWORD 0 */ - u8 axgmac1_ue_status; /* DWORD 0 */ - u8 mpu_intpend_ue_status; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_LOW_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Status (High) Register. Each bit corresponds to - * an internal Unrecoverable Error. These are set by hardware and may be - * cleared by writing a one to the respective bit(s) to be cleared. Any - * bit being set that is also unmasked will result in Unrecoverable Error - * interrupt notification to the host CPU and/or Server Management chip; - * and the transitioning of BladeEngine to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP { - u8 jtag_ue_status; /* DWORD 0 */ - u8 lpcmemhost_ue_status; /* DWORD 0 */ - u8 mgmt_mac_ue_status; /* DWORD 0 */ - u8 mpu_iram_ue_status; /* DWORD 0 */ - u8 pcs0online_ue_status; /* DWORD 0 */ - u8 pcs1online_ue_status; /* DWORD 0 */ - u8 pctl0_ue_status; /* DWORD 0 */ - u8 pctl1_ue_status; /* DWORD 0 */ - u8 pmem_ue_status; /* DWORD 0 */ - u8 rr_ue_status; /* DWORD 0 */ - u8 rxpp_ue_status; /* DWORD 0 */ - u8 txpb_ue_status; /* DWORD 0 */ - u8 txp_ue_status; /* DWORD 0 */ - u8 xaui_ue_status; /* DWORD 0 */ - u8 arm_ue_status; /* DWORD 0 */ - u8 ipc_ue_status; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Mask (Low) Register. Each bit, when set to one, - * will mask the associated Unrecoverable Error status bit from notification - * of Unrecoverable Error to the host CPU and/or Server Managment chip and the - * transitioning of all BladeEngine units to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP { - u8 cev_ue_mask; /* DWORD 0 */ - u8 ctx_ue_mask; /* DWORD 0 */ - u8 dbuf_ue_mask; /* DWORD 0 */ - u8 erx_ue_mask; /* DWORD 0 */ - u8 host_ue_mask; /* DWORD 0 */ - u8 mpu_ue_mask; /* DWORD 0 */ - u8 ndma_ue_mask; /* DWORD 0 */ - u8 ptc_ue_mask; /* DWORD 0 */ - u8 rdma_ue_mask; /* DWORD 0 */ - u8 rxf_ue_mask; /* DWORD 0 */ - u8 rxips_ue_mask; /* DWORD 0 */ - u8 rxulp0_ue_mask; /* DWORD 0 */ - u8 rxulp1_ue_mask; /* DWORD 0 */ - u8 rxulp2_ue_mask; /* DWORD 0 */ - u8 tim_ue_mask; /* DWORD 0 */ - u8 tpost_ue_mask; /* DWORD 0 */ - u8 tpre_ue_mask; /* DWORD 0 */ - u8 txips_ue_mask; /* DWORD 0 */ - u8 txulp0_ue_mask; /* DWORD 0 */ - u8 txulp1_ue_mask; /* DWORD 0 */ - u8 uc_ue_mask; /* DWORD 0 */ - u8 wdma_ue_mask; /* DWORD 0 */ - u8 txulp2_ue_mask; /* DWORD 0 */ - u8 host1_ue_mask; /* DWORD 0 */ - u8 p0_ob_link_ue_mask; /* DWORD 0 */ - u8 p1_ob_link_ue_mask; /* DWORD 0 */ - u8 host_gpio_ue_mask; /* DWORD 0 */ - u8 mbox_netw_ue_mask; /* DWORD 0 */ - u8 mbox_stor_ue_mask; /* DWORD 0 */ - u8 axgmac0_ue_mask; /* DWORD 0 */ - u8 axgmac1_ue_mask; /* DWORD 0 */ - u8 mpu_intpend_ue_mask; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Mask (High) Register. Each bit, when set to one, - * will mask the associated Unrecoverable Error status bit from notification - * of Unrecoverable Error to the host CPU and/or Server Managment chip and the - * transitioning of all BladeEngine units to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP { - u8 jtag_ue_mask; /* DWORD 0 */ - u8 lpcmemhost_ue_mask; /* DWORD 0 */ - u8 mgmt_mac_ue_mask; /* DWORD 0 */ - u8 mpu_iram_ue_mask; /* DWORD 0 */ - u8 pcs0online_ue_mask; /* DWORD 0 */ - u8 pcs1online_ue_mask; /* DWORD 0 */ - u8 pctl0_ue_mask; /* DWORD 0 */ - u8 pctl1_ue_mask; /* DWORD 0 */ - u8 pmem_ue_mask; /* DWORD 0 */ - u8 rr_ue_mask; /* DWORD 0 */ - u8 rxpp_ue_mask; /* DWORD 0 */ - u8 txpb_ue_mask; /* DWORD 0 */ - u8 txp_ue_mask; /* DWORD 0 */ - u8 xaui_ue_mask; /* DWORD 0 */ - u8 arm_ue_mask; /* DWORD 0 */ - u8 ipc_ue_mask; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_HI_MASK_CSR_AMAP { - u32 dw[1]; -}; - -/* Online Control Register 0. This register controls various units within - * BladeEngine being in an Online or Offline state. - */ -struct BE_PCICFG_ONLINE0_CSR_AMAP { - u8 cev_online; /* DWORD 0 */ - u8 ctx_online; /* DWORD 0 */ - u8 dbuf_online; /* DWORD 0 */ - u8 erx_online; /* DWORD 0 */ - u8 host_online; /* DWORD 0 */ - u8 mpu_online; /* DWORD 0 */ - u8 ndma_online; /* DWORD 0 */ - u8 ptc_online; /* DWORD 0 */ - u8 rdma_online; /* DWORD 0 */ - u8 rxf_online; /* DWORD 0 */ - u8 rxips_online; /* DWORD 0 */ - u8 rxulp0_online; /* DWORD 0 */ - u8 rxulp1_online; /* DWORD 0 */ - u8 rxulp2_online; /* DWORD 0 */ - u8 tim_online; /* DWORD 0 */ - u8 tpost_online; /* DWORD 0 */ - u8 tpre_online; /* DWORD 0 */ - u8 txips_online; /* DWORD 0 */ - u8 txulp0_online; /* DWORD 0 */ - u8 txulp1_online; /* DWORD 0 */ - u8 uc_online; /* DWORD 0 */ - u8 wdma_online; /* DWORD 0 */ - u8 txulp2_online; /* DWORD 0 */ - u8 host1_online; /* DWORD 0 */ - u8 p0_ob_link_online; /* DWORD 0 */ - u8 p1_ob_link_online; /* DWORD 0 */ - u8 host_gpio_online; /* DWORD 0 */ - u8 mbox_netw_online; /* DWORD 0 */ - u8 mbox_stor_online; /* DWORD 0 */ - u8 axgmac0_online; /* DWORD 0 */ - u8 axgmac1_online; /* DWORD 0 */ - u8 mpu_intpend_online; /* DWORD 0 */ -} __packed; -struct PCICFG_ONLINE0_CSR_AMAP { - u32 dw[1]; -}; - -/* Online Control Register 1. This register controls various units within - * BladeEngine being in an Online or Offline state. - */ -struct BE_PCICFG_ONLINE1_CSR_AMAP { - u8 jtag_online; /* DWORD 0 */ - u8 lpcmemhost_online; /* DWORD 0 */ - u8 mgmt_mac_online; /* DWORD 0 */ - u8 mpu_iram_online; /* DWORD 0 */ - u8 pcs0online_online; /* DWORD 0 */ - u8 pcs1online_online; /* DWORD 0 */ - u8 pctl0_online; /* DWORD 0 */ - u8 pctl1_online; /* DWORD 0 */ - u8 pmem_online; /* DWORD 0 */ - u8 rr_online; /* DWORD 0 */ - u8 rxpp_online; /* DWORD 0 */ - u8 txpb_online; /* DWORD 0 */ - u8 txp_online; /* DWORD 0 */ - u8 xaui_online; /* DWORD 0 */ - u8 arm_online; /* DWORD 0 */ - u8 ipc_online; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_ONLINE1_CSR_AMAP { - u32 dw[1]; -}; - -/* Host Timer Register. */ -struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP { - u8 hosttimer[24]; /* DWORD 0 */ - u8 hostintr; /* DWORD 0 */ - u8 rsvd0[7]; /* DWORD 0 */ -} __packed; -struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP { - u32 dw[1]; -}; - -/* Scratchpad Register (for software use). */ -struct BE_PCICFG_SCRATCHPAD_CSR_AMAP { - u8 scratchpad[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_SCRATCHPAD_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Capabilities Register. */ -struct BE_PCICFG_PCIE_CAP_CSR_AMAP { - u8 capid[8]; /* DWORD 0 */ - u8 nextcap[8]; /* DWORD 0 */ - u8 capver[4]; /* DWORD 0 */ - u8 devport[4]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_CAP_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Device Capabilities Register. */ -struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP { - u8 payload[3]; /* DWORD 0 */ - u8 rsvd0[3]; /* DWORD 0 */ - u8 lo_lat[3]; /* DWORD 0 */ - u8 l1_lat[3]; /* DWORD 0 */ - u8 rsvd1[3]; /* DWORD 0 */ - u8 rsvd2[3]; /* DWORD 0 */ - u8 pwr_value[8]; /* DWORD 0 */ - u8 pwr_scale[2]; /* DWORD 0 */ - u8 rsvd3[4]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_DEVCAP_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Device Control/Status Registers. */ -struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP { - u8 CorrErrReportEn; /* DWORD 0 */ - u8 NonFatalErrReportEn; /* DWORD 0 */ - u8 FatalErrReportEn; /* DWORD 0 */ - u8 UnsuppReqReportEn; /* DWORD 0 */ - u8 EnableRelaxOrder; /* DWORD 0 */ - u8 Max_Payload_Size[3]; /* DWORD 0 */ - u8 ExtendTagFieldEnable; /* DWORD 0 */ - u8 PhantomFnEnable; /* DWORD 0 */ - u8 AuxPwrPMEnable; /* DWORD 0 */ - u8 EnableNoSnoop; /* DWORD 0 */ - u8 Max_Read_Req_Size[3]; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 CorrErrDetect; /* DWORD 0 */ - u8 NonFatalErrDetect; /* DWORD 0 */ - u8 FatalErrDetect; /* DWORD 0 */ - u8 UnsuppReqDetect; /* DWORD 0 */ - u8 AuxPwrDetect; /* DWORD 0 */ - u8 TransPending; /* DWORD 0 */ - u8 rsvd1[10]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Link Capabilities Register. */ -struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP { - u8 MaxLinkSpeed[4]; /* DWORD 0 */ - u8 MaxLinkWidth[6]; /* DWORD 0 */ - u8 ASPMSupport[2]; /* DWORD 0 */ - u8 L0sExitLat[3]; /* DWORD 0 */ - u8 L1ExitLat[3]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 PortNum[8]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_LINK_CAP_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Link Status Register. */ -struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP { - u8 ASPMCtl[2]; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 ReadCmplBndry; /* DWORD 0 */ - u8 LinkDisable; /* DWORD 0 */ - u8 RetrainLink; /* DWORD 0 */ - u8 CommonClkConfig; /* DWORD 0 */ - u8 ExtendSync; /* DWORD 0 */ - u8 rsvd1[8]; /* DWORD 0 */ - u8 LinkSpeed[4]; /* DWORD 0 */ - u8 NegLinkWidth[6]; /* DWORD 0 */ - u8 LinkTrainErr; /* DWORD 0 */ - u8 LinkTrain; /* DWORD 0 */ - u8 SlotClkConfig; /* DWORD 0 */ - u8 rsvd2[3]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_LINK_STATUS_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI Configuration Register. */ -struct BE_PCICFG_MSI_CSR_AMAP { - u8 capid[8]; /* DWORD 0 */ - u8 nextptr[8]; /* DWORD 0 */ - u8 tablesize[11]; /* DWORD 0 */ - u8 rsvd0[3]; /* DWORD 0 */ - u8 funcmask; /* DWORD 0 */ - u8 en; /* DWORD 0 */ -} __packed; -struct PCICFG_MSI_CSR_AMAP { - u32 dw[1]; -}; - -/* MSI-X Table Offset Register. */ -struct BE_PCICFG_MSIX_TABLE_CSR_AMAP { - u8 tablebir[3]; /* DWORD 0 */ - u8 offset[29]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_TABLE_CSR_AMAP { - u32 dw[1]; -}; - -/* MSI-X PBA Offset Register. */ -struct BE_PCICFG_MSIX_PBA_CSR_AMAP { - u8 pbabir[3]; /* DWORD 0 */ - u8 offset[29]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_PBA_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Vector Control Register. */ -struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP { - u8 vector_control; /* DWORD 0 */ - u8 rsvd0[31]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Data Register. */ -struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP { - u8 data[16]; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_MSG_DATA_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Address Register - High Part. */ -struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP { - u8 addr[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Address Register - Low Part. */ -struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP { - u8 rsvd0[2]; /* DWORD 0 */ - u8 addr[30]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_18_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_18_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_19_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_19_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_20_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[25][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_20_RSVD_AMAP { - u32 dw[26]; -}; - -struct BE_PCICFG_ANON_21_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[1919][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_21_RSVD_AMAP { - u32 dw[1920]; -}; - -struct BE_PCICFG_ANON_22_MESSAGE_AMAP { - struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP vec_ctrl; - struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP msg_data; - struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP addr_hi; - struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP addr_low; -} __packed; -struct PCICFG_ANON_22_MESSAGE_AMAP { - u32 dw[4]; -}; - -struct BE_PCICFG_ANON_23_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[895][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_23_RSVD_AMAP { - u32 dw[896]; -}; - -/* These PCI Configuration Space registers are for the Storage Function of - * BladeEngine (Function 0). In the memory map of the registers below their - * table, - */ -struct BE_PCICFG0_CSRMAP_AMAP { - struct BE_PCICFG_ID_CSR_AMAP id; - u8 rsvd0[32]; /* DWORD 1 */ - u8 rsvd1[32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 3 */ - struct BE_PCICFG_IOBAR_CSR_AMAP iobar; - struct BE_PCICFG_MEMBAR0_CSR_AMAP membar0; - struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP membar1_lo; - struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP membar1_hi; - struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP membar2_lo; - struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP membar2_hi; - u8 rsvd3[32]; /* DWORD 10 */ - struct BE_PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP subsystem_id; - u8 rsvd4[32]; /* DWORD 12 */ - u8 rsvd5[32]; /* DWORD 13 */ - u8 rsvd6[32]; /* DWORD 14 */ - u8 rsvd7[32]; /* DWORD 15 */ - struct BE_PCICFG_SEMAPHORE_CSR_AMAP semaphore[4]; - struct BE_PCICFG_SOFT_RESET_CSR_AMAP soft_reset; - u8 rsvd8[32]; /* DWORD 21 */ - struct BE_PCICFG_SCRATCHPAD_CSR_AMAP scratchpad; - u8 rsvd9[32]; /* DWORD 23 */ - u8 rsvd10[32]; /* DWORD 24 */ - u8 rsvd11[32]; /* DWORD 25 */ - u8 rsvd12[32]; /* DWORD 26 */ - u8 rsvd13[32]; /* DWORD 27 */ - u8 rsvd14[2][32]; /* DWORD 28 */ - u8 rsvd15[32]; /* DWORD 30 */ - u8 rsvd16[32]; /* DWORD 31 */ - u8 rsvd17[8][32]; /* DWORD 32 */ - struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP ue_status_low; - struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP ue_status_hi; - struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP ue_status_low_mask; - struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP ue_status_hi_mask; - struct BE_PCICFG_ONLINE0_CSR_AMAP online0; - struct BE_PCICFG_ONLINE1_CSR_AMAP online1; - u8 rsvd18[32]; /* DWORD 46 */ - u8 rsvd19[32]; /* DWORD 47 */ - u8 rsvd20[32]; /* DWORD 48 */ - u8 rsvd21[32]; /* DWORD 49 */ - struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP host_timer_int_ctrl; - u8 rsvd22[32]; /* DWORD 51 */ - struct BE_PCICFG_PCIE_CAP_CSR_AMAP pcie_cap; - struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP pcie_devcap; - struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP pcie_control_status; - struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP pcie_link_cap; - struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP pcie_link_status; - struct BE_PCICFG_MSI_CSR_AMAP msi; - struct BE_PCICFG_MSIX_TABLE_CSR_AMAP msix_table_offset; - struct BE_PCICFG_MSIX_PBA_CSR_AMAP msix_pba_offset; - u8 rsvd23[32]; /* DWORD 60 */ - u8 rsvd24[32]; /* DWORD 61 */ - u8 rsvd25[32]; /* DWORD 62 */ - u8 rsvd26[32]; /* DWORD 63 */ - u8 rsvd27[32]; /* DWORD 64 */ - u8 rsvd28[32]; /* DWORD 65 */ - u8 rsvd29[32]; /* DWORD 66 */ - u8 rsvd30[32]; /* DWORD 67 */ - u8 rsvd31[32]; /* DWORD 68 */ - u8 rsvd32[32]; /* DWORD 69 */ - u8 rsvd33[32]; /* DWORD 70 */ - u8 rsvd34[32]; /* DWORD 71 */ - u8 rsvd35[32]; /* DWORD 72 */ - u8 rsvd36[32]; /* DWORD 73 */ - u8 rsvd37[32]; /* DWORD 74 */ - u8 rsvd38[32]; /* DWORD 75 */ - u8 rsvd39[32]; /* DWORD 76 */ - u8 rsvd40[32]; /* DWORD 77 */ - u8 rsvd41[32]; /* DWORD 78 */ - u8 rsvd42[32]; /* DWORD 79 */ - u8 rsvd43[32]; /* DWORD 80 */ - u8 rsvd44[32]; /* DWORD 81 */ - u8 rsvd45[32]; /* DWORD 82 */ - u8 rsvd46[32]; /* DWORD 83 */ - u8 rsvd47[32]; /* DWORD 84 */ - u8 rsvd48[32]; /* DWORD 85 */ - u8 rsvd49[32]; /* DWORD 86 */ - u8 rsvd50[32]; /* DWORD 87 */ - u8 rsvd51[32]; /* DWORD 88 */ - u8 rsvd52[32]; /* DWORD 89 */ - u8 rsvd53[32]; /* DWORD 90 */ - u8 rsvd54[32]; /* DWORD 91 */ - u8 rsvd55[32]; /* DWORD 92 */ - u8 rsvd56[832]; /* DWORD 93 */ - u8 rsvd57[32]; /* DWORD 119 */ - u8 rsvd58[32]; /* DWORD 120 */ - u8 rsvd59[32]; /* DWORD 121 */ - u8 rsvd60[32]; /* DWORD 122 */ - u8 rsvd61[32]; /* DWORD 123 */ - u8 rsvd62[32]; /* DWORD 124 */ - u8 rsvd63[32]; /* DWORD 125 */ - u8 rsvd64[32]; /* DWORD 126 */ - u8 rsvd65[32]; /* DWORD 127 */ - u8 rsvd66[61440]; /* DWORD 128 */ - struct BE_PCICFG_ANON_22_MESSAGE_AMAP message[32]; - u8 rsvd67[28672]; /* DWORD 2176 */ - u8 rsvd68[32]; /* DWORD 3072 */ - u8 rsvd69[1023][32]; /* DWORD 3073 */ -} __packed; -struct PCICFG0_CSRMAP_AMAP { - u32 dw[4096]; -}; - -struct BE_PCICFG_ANON_24_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_24_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_25_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_25_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_26_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_26_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_27_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_27_RSVD_AMAP { - u32 dw[2]; -}; - -struct BE_PCICFG_ANON_28_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[3][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_28_RSVD_AMAP { - u32 dw[4]; -}; - -struct BE_PCICFG_ANON_29_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[36][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_29_RSVD_AMAP { - u32 dw[37]; -}; - -struct BE_PCICFG_ANON_30_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[1930][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_30_RSVD_AMAP { - u32 dw[1931]; -}; - -struct BE_PCICFG_ANON_31_MESSAGE_AMAP { - struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP vec_ctrl; - struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP msg_data; - struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP addr_hi; - struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP addr_low; -} __packed; -struct PCICFG_ANON_31_MESSAGE_AMAP { - u32 dw[4]; -}; - -struct BE_PCICFG_ANON_32_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[895][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_32_RSVD_AMAP { - u32 dw[896]; -}; - -/* This PCI configuration space register map is for the Networking Function of - * BladeEngine (Function 1). - */ -struct BE_PCICFG1_CSRMAP_AMAP { - struct BE_PCICFG_ID_CSR_AMAP id; - u8 rsvd0[32]; /* DWORD 1 */ - u8 rsvd1[32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 3 */ - struct BE_PCICFG_IOBAR_CSR_AMAP iobar; - struct BE_PCICFG_MEMBAR0_CSR_AMAP membar0; - struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP membar1_lo; - struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP membar1_hi; - struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP membar2_lo; - struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP membar2_hi; - u8 rsvd3[32]; /* DWORD 10 */ - struct BE_PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP subsystem_id; - u8 rsvd4[32]; /* DWORD 12 */ - u8 rsvd5[32]; /* DWORD 13 */ - u8 rsvd6[32]; /* DWORD 14 */ - u8 rsvd7[32]; /* DWORD 15 */ - struct BE_PCICFG_SEMAPHORE_CSR_AMAP semaphore[4]; - struct BE_PCICFG_SOFT_RESET_CSR_AMAP soft_reset; - u8 rsvd8[32]; /* DWORD 21 */ - struct BE_PCICFG_SCRATCHPAD_CSR_AMAP scratchpad; - u8 rsvd9[32]; /* DWORD 23 */ - u8 rsvd10[32]; /* DWORD 24 */ - u8 rsvd11[32]; /* DWORD 25 */ - u8 rsvd12[32]; /* DWORD 26 */ - u8 rsvd13[32]; /* DWORD 27 */ - u8 rsvd14[2][32]; /* DWORD 28 */ - u8 rsvd15[32]; /* DWORD 30 */ - u8 rsvd16[32]; /* DWORD 31 */ - u8 rsvd17[8][32]; /* DWORD 32 */ - struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP ue_status_low; - struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP ue_status_hi; - struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP ue_status_low_mask; - struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP ue_status_hi_mask; - struct BE_PCICFG_ONLINE0_CSR_AMAP online0; - struct BE_PCICFG_ONLINE1_CSR_AMAP online1; - u8 rsvd18[32]; /* DWORD 46 */ - u8 rsvd19[32]; /* DWORD 47 */ - u8 rsvd20[32]; /* DWORD 48 */ - u8 rsvd21[32]; /* DWORD 49 */ - struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP host_timer_int_ctrl; - u8 rsvd22[32]; /* DWORD 51 */ - struct BE_PCICFG_PCIE_CAP_CSR_AMAP pcie_cap; - struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP pcie_devcap; - struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP pcie_control_status; - struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP pcie_link_cap; - struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP pcie_link_status; - struct BE_PCICFG_MSI_CSR_AMAP msi; - struct BE_PCICFG_MSIX_TABLE_CSR_AMAP msix_table_offset; - struct BE_PCICFG_MSIX_PBA_CSR_AMAP msix_pba_offset; - u8 rsvd23[64]; /* DWORD 60 */ - u8 rsvd24[32]; /* DWORD 62 */ - u8 rsvd25[32]; /* DWORD 63 */ - u8 rsvd26[32]; /* DWORD 64 */ - u8 rsvd27[32]; /* DWORD 65 */ - u8 rsvd28[32]; /* DWORD 66 */ - u8 rsvd29[32]; /* DWORD 67 */ - u8 rsvd30[32]; /* DWORD 68 */ - u8 rsvd31[32]; /* DWORD 69 */ - u8 rsvd32[32]; /* DWORD 70 */ - u8 rsvd33[32]; /* DWORD 71 */ - u8 rsvd34[32]; /* DWORD 72 */ - u8 rsvd35[32]; /* DWORD 73 */ - u8 rsvd36[32]; /* DWORD 74 */ - u8 rsvd37[128]; /* DWORD 75 */ - u8 rsvd38[32]; /* DWORD 79 */ - u8 rsvd39[1184]; /* DWORD 80 */ - u8 rsvd40[61792]; /* DWORD 117 */ - struct BE_PCICFG_ANON_31_MESSAGE_AMAP message[32]; - u8 rsvd41[28672]; /* DWORD 2176 */ - u8 rsvd42[32]; /* DWORD 3072 */ - u8 rsvd43[1023][32]; /* DWORD 3073 */ -} __packed; -struct PCICFG1_CSRMAP_AMAP { - u32 dw[4096]; -}; - -#endif /* __pcicfg_amap_h__ */ diff --git a/drivers/staging/benet/post_codes.h b/drivers/staging/benet/post_codes.h deleted file mode 100644 index 6d1621f5f5fb..000000000000 --- a/drivers/staging/benet/post_codes.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __post_codes_amap_h__ -#define __post_codes_amap_h__ - -/* --- MGMT_HBA_POST_STAGE_ENUM --- */ -#define POST_STAGE_POWER_ON_RESET (0) /* State after a cold or warm boot. */ -#define POST_STAGE_AWAITING_HOST_RDY (1) /* ARM boot code awaiting a - go-ahed from the host. */ -#define POST_STAGE_HOST_RDY (2) /* Host has given go-ahed to ARM. */ -#define POST_STAGE_BE_RESET (3) /* Host wants to reset chip, this is a chip - workaround */ -#define POST_STAGE_SEEPROM_CS_START (256) /* SEEPROM checksum - test start. */ -#define POST_STAGE_SEEPROM_CS_DONE (257) /* SEEPROM checksum test - done. */ -#define POST_STAGE_DDR_CONFIG_START (512) /* DDR configuration start. */ -#define POST_STAGE_DDR_CONFIG_DONE (513) /* DDR configuration done. */ -#define POST_STAGE_DDR_CALIBRATE_START (768) /* DDR calibration start. */ -#define POST_STAGE_DDR_CALIBRATE_DONE (769) /* DDR calibration done. */ -#define POST_STAGE_DDR_TEST_START (1024) /* DDR memory test start. */ -#define POST_STAGE_DDR_TEST_DONE (1025) /* DDR memory test done. */ -#define POST_STAGE_REDBOOT_INIT_START (1536) /* Redboot starts execution. */ -#define POST_STAGE_REDBOOT_INIT_DONE (1537) /* Redboot done execution. */ -#define POST_STAGE_FW_IMAGE_LOAD_START (1792) /* Firmware image load to - DDR start. */ -#define POST_STAGE_FW_IMAGE_LOAD_DONE (1793) /* Firmware image load - to DDR done. */ -#define POST_STAGE_ARMFW_START (2048) /* ARMfw runtime code - starts execution. */ -#define POST_STAGE_DHCP_QUERY_START (2304) /* DHCP server query start. */ -#define POST_STAGE_DHCP_QUERY_DONE (2305) /* DHCP server query done. */ -#define POST_STAGE_BOOT_TARGET_DISCOVERY_START (2560) /* Boot Target - Discovery Start. */ -#define POST_STAGE_BOOT_TARGET_DISCOVERY_DONE (2561) /* Boot Target - Discovery Done. */ -#define POST_STAGE_RC_OPTION_SET (2816) /* Remote configuration - option is set in SEEPROM */ -#define POST_STAGE_SWITCH_LINK (2817) /* Wait for link up on switch */ -#define POST_STAGE_SEND_ICDS_MESSAGE (2818) /* Send the ICDS message - to switch */ -#define POST_STAGE_PERFROM_TFTP (2819) /* Download xml using TFTP */ -#define POST_STAGE_PARSE_XML (2820) /* Parse XML file */ -#define POST_STAGE_DOWNLOAD_IMAGE (2821) /* Download IMAGE from - TFTP server */ -#define POST_STAGE_FLASH_IMAGE (2822) /* Flash the IMAGE */ -#define POST_STAGE_RC_DONE (2823) /* Remote configuration - complete */ -#define POST_STAGE_REBOOT_SYSTEM (2824) /* Upgrade IMAGE done, - reboot required */ -#define POST_STAGE_MAC_ADDRESS (3072) /* MAC Address Check */ -#define POST_STAGE_ARMFW_READY (49152) /* ARMfw is done with POST - and ready. */ -#define POST_STAGE_ARMFW_UE (61440) /* ARMfw has asserted an - unrecoverable error. The - lower 3 hex digits of the - stage code identify the - unique error code. - */ - -/* This structure defines the format of the MPU semaphore - * register when used for POST. - */ -struct BE_MGMT_HBA_POST_STATUS_STRUCT_AMAP { - u8 stage[16]; /* DWORD 0 */ - u8 rsvd0[10]; /* DWORD 0 */ - u8 iscsi_driver_loaded; /* DWORD 0 */ - u8 option_rom_installed; /* DWORD 0 */ - u8 iscsi_ip_conflict; /* DWORD 0 */ - u8 iscsi_no_ip; /* DWORD 0 */ - u8 backup_fw; /* DWORD 0 */ - u8 error; /* DWORD 0 */ -} __packed; -struct MGMT_HBA_POST_STATUS_STRUCT_AMAP { - u32 dw[1]; -}; - -/* --- MGMT_HBA_POST_DUMMY_BITS_ENUM --- */ -#define POST_BIT_ISCSI_LOADED (26) -#define POST_BIT_OPTROM_INST (27) -#define POST_BIT_BAD_IP_ADDR (28) -#define POST_BIT_NO_IP_ADDR (29) -#define POST_BIT_BACKUP_FW (30) -#define POST_BIT_ERROR (31) - -/* --- MGMT_HBA_POST_DUMMY_VALUES_ENUM --- */ -#define POST_ISCSI_DRIVER_LOADED (67108864) -#define POST_OPTROM_INSTALLED (134217728) -#define POST_ISCSI_IP_ADDRESS_CONFLICT (268435456) -#define POST_ISCSI_NO_IP_ADDRESS (536870912) -#define POST_BACKUP_FW_LOADED (1073741824) -#define POST_FATAL_ERROR (2147483648) - -#endif /* __post_codes_amap_h__ */ diff --git a/drivers/staging/benet/regmap.h b/drivers/staging/benet/regmap.h deleted file mode 100644 index e816ba210e83..000000000000 --- a/drivers/staging/benet/regmap.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __regmap_amap_h__ -#define __regmap_amap_h__ -#include "pcicfg.h" -#include "ep.h" -#include "cev.h" -#include "mpu.h" -#include "doorbells.h" - -/* - * This is the control and status register map for BladeEngine, showing - * the relative size and offset of each sub-module. The CSR registers - * are identical for the network and storage PCI functions. The - * CSR map is shown below, followed by details of each block, - * in sub-sections. The sub-sections begin with a description - * of CSRs that are instantiated in multiple blocks. - */ -struct BE_BLADE_ENGINE_CSRMAP_AMAP { - struct BE_MPU_CSRMAP_AMAP mpu; - u8 rsvd0[8192]; /* DWORD 256 */ - u8 rsvd1[8192]; /* DWORD 512 */ - struct BE_CEV_CSRMAP_AMAP cev; - u8 rsvd2[8192]; /* DWORD 1024 */ - u8 rsvd3[8192]; /* DWORD 1280 */ - u8 rsvd4[8192]; /* DWORD 1536 */ - u8 rsvd5[8192]; /* DWORD 1792 */ - u8 rsvd6[8192]; /* DWORD 2048 */ - u8 rsvd7[8192]; /* DWORD 2304 */ - u8 rsvd8[8192]; /* DWORD 2560 */ - u8 rsvd9[8192]; /* DWORD 2816 */ - u8 rsvd10[8192]; /* DWORD 3072 */ - u8 rsvd11[8192]; /* DWORD 3328 */ - u8 rsvd12[8192]; /* DWORD 3584 */ - u8 rsvd13[8192]; /* DWORD 3840 */ - u8 rsvd14[8192]; /* DWORD 4096 */ - u8 rsvd15[8192]; /* DWORD 4352 */ - u8 rsvd16[8192]; /* DWORD 4608 */ - u8 rsvd17[8192]; /* DWORD 4864 */ - u8 rsvd18[8192]; /* DWORD 5120 */ - u8 rsvd19[8192]; /* DWORD 5376 */ - u8 rsvd20[8192]; /* DWORD 5632 */ - u8 rsvd21[8192]; /* DWORD 5888 */ - u8 rsvd22[8192]; /* DWORD 6144 */ - u8 rsvd23[17152][32]; /* DWORD 6400 */ -} __packed; -struct BLADE_ENGINE_CSRMAP_AMAP { - u32 dw[23552]; -}; - -#endif /* __regmap_amap_h__ */ -- cgit v1.2.3 From 690103137267e9ed893febf7ff061af63e8235a9 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Wed, 18 Mar 2009 18:11:51 -0700 Subject: bnx2: Fix problem of using wrong IRQ handler. The MSI-X handler was chosen before the call to pci_enable_msix(). If MSI-X was not available, the wrong MSI-X handler would be used in INTA mode. This would cause a screaming interrupt problem because INTA would not be cleared by the MSI-X handler. Fixed by assigning MSI-X handler after pci_enable_msix() returns successfully. Also update version to 1.9.3. Thomas Chenault helped us find this problem. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 6500b7c4739f..6b6530ffdf19 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -57,8 +57,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.9.2" -#define DRV_MODULE_RELDATE "Feb 11, 2009" +#define DRV_MODULE_VERSION "1.9.3" +#define DRV_MODULE_RELDATE "March 17, 2009" #define RUN_AT(x) (jiffies + (x)) @@ -5843,9 +5843,6 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs) for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) { msix_ent[i].entry = i; msix_ent[i].vector = 0; - - snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i); - bp->irq_tbl[i].handler = bnx2_msi_1shot; } rc = pci_enable_msix(bp->pdev, msix_ent, BNX2_MAX_MSIX_VEC); @@ -5854,8 +5851,11 @@ bnx2_enable_msix(struct bnx2 *bp, int msix_vecs) bp->irq_nvecs = msix_vecs; bp->flags |= BNX2_FLAG_USING_MSIX | BNX2_FLAG_ONE_SHOT_MSI; - for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) + for (i = 0; i < BNX2_MAX_MSIX_VEC; i++) { bp->irq_tbl[i].vector = msix_ent[i].vector; + snprintf(bp->irq_tbl[i].name, len, "%s-%d", dev->name, i); + bp->irq_tbl[i].handler = bnx2_msi_1shot; + } } static void -- cgit v1.2.3 From 17d04500e2528217de5fe967599f98ee84348a9c Mon Sep 17 00:00:00 2001 From: Jay Vosburgh Date: Wed, 18 Mar 2009 18:38:25 -0700 Subject: bonding: Fix updating of speed/duplex changes This patch corrects an omission from the following commit: commit f0c76d61779b153dbfb955db3f144c62d02173c2 Author: Jay Vosburgh Date: Wed Jul 2 18:21:58 2008 -0700 bonding: refactor mii monitor The un-refactored code checked the link speed and duplex of every slave on every pass; the refactored code did not do so. The 802.3ad and balance-alb/tlb modes utilize the speed and duplex information, and require it to be kept up to date. This patch adds a notifier check to perform the appropriate updating when the slave device speed changes. Signed-off-by: Jay Vosburgh Signed-off-by: David S. Miller --- drivers/net/bonding/bond_main.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index e0578fe8c0db..3d76686dceca 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3537,11 +3537,26 @@ static int bond_slave_netdev_event(unsigned long event, struct net_device *slave } break; case NETDEV_CHANGE: - /* - * TODO: is this what we get if somebody - * sets up a hierarchical bond, then rmmod's - * one of the slave bonding devices? - */ + if (bond->params.mode == BOND_MODE_8023AD || bond_is_lb(bond)) { + struct slave *slave; + + slave = bond_get_slave_by_dev(bond, slave_dev); + if (slave) { + u16 old_speed = slave->speed; + u16 old_duplex = slave->duplex; + + bond_update_speed_duplex(slave); + + if (bond_is_lb(bond)) + break; + + if (old_speed != slave->speed) + bond_3ad_adapter_speed_changed(slave); + if (old_duplex != slave->duplex) + bond_3ad_adapter_duplex_changed(slave); + } + } + break; case NETDEV_DOWN: /* -- cgit v1.2.3 From 4783256ef92f5aecd6d54693b16386f2a0021c2a Mon Sep 17 00:00:00 2001 From: Pantelis Koukousoulas Date: Wed, 18 Mar 2009 18:40:02 -0700 Subject: virtio_net: Make virtio_net support carrier detection Impact: Make NetworkManager work with virtio_net For now the semantics are simple: There is always carrier. This allows a seamless experience with e.g., qemu/kvm where NetworkManager just configures and sets up everything automagically. If/when a generally agreed-upon way to control carrier on/off in the emulator/hypervisor level emerges, it will be trivial to extend the driver to support that too, but for now even this 2-liner makes user experience that much better. Signed-off-by: Pantelis Koukousoulas Signed-off-by: Rusty Russell Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index c68808336c8c..e67d16c2e5f3 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -612,6 +612,7 @@ static struct ethtool_ops virtnet_ethtool_ops = { .set_tx_csum = virtnet_set_tx_csum, .set_sg = ethtool_op_set_sg, .set_tso = ethtool_op_set_tso, + .get_link = ethtool_op_get_link, }; #define MIN_MTU 68 @@ -739,6 +740,8 @@ static int virtnet_probe(struct virtio_device *vdev) goto unregister; } + netif_carrier_on(dev); + pr_debug("virtnet: registered device %s\n", dev->name); return 0; -- cgit v1.2.3 From 69145635d4db0a0382885b14634aa5b721f3aa1a Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Wed, 18 Mar 2009 18:49:01 -0700 Subject: tulip: fix crash on iface up with shirq debug Tulip is currently doing request_irq before it has done its initialization. This is usually not a problem because it hasn't enable interrupts yet, but with DEBUG_SHIRQ on, we call the irq handler when registering the interrupt as a sanity check. This can result in a NULL ptr dereference, so call tulip_init_ring before request_irq, and add a free_ring function to do the freeing now shared with tulip_close. Tested with a shell loop running ifup, ifdown in a loop a few hundred times with DEBUG_SHIRQ on. Signed-off-by: Kyle McMartin Signed-off-by: David S. Miller --- drivers/net/tulip/tulip_core.c | 45 +++++++++++++++++++++++++++--------------- 1 file changed, 29 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tulip/tulip_core.c b/drivers/net/tulip/tulip_core.c index bee75fa87a9c..2abb5d3becc6 100644 --- a/drivers/net/tulip/tulip_core.c +++ b/drivers/net/tulip/tulip_core.c @@ -255,6 +255,7 @@ const char tulip_media_cap[32] = static void tulip_tx_timeout(struct net_device *dev); static void tulip_init_ring(struct net_device *dev); +static void tulip_free_ring(struct net_device *dev); static int tulip_start_xmit(struct sk_buff *skb, struct net_device *dev); static int tulip_open(struct net_device *dev); static int tulip_close(struct net_device *dev); @@ -502,16 +503,21 @@ tulip_open(struct net_device *dev) { int retval; - if ((retval = request_irq(dev->irq, &tulip_interrupt, IRQF_SHARED, dev->name, dev))) - return retval; - tulip_init_ring (dev); + retval = request_irq(dev->irq, &tulip_interrupt, IRQF_SHARED, dev->name, dev); + if (retval) + goto free_ring; + tulip_up (dev); netif_start_queue (dev); return 0; + +free_ring: + tulip_free_ring (dev); + return retval; } @@ -768,23 +774,11 @@ static void tulip_down (struct net_device *dev) tulip_set_power_state (tp, 0, 1); } - -static int tulip_close (struct net_device *dev) +static void tulip_free_ring (struct net_device *dev) { struct tulip_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->base_addr; int i; - netif_stop_queue (dev); - - tulip_down (dev); - - if (tulip_debug > 1) - printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", - dev->name, ioread32 (ioaddr + CSR5)); - - free_irq (dev->irq, dev); - /* Free all the skbuffs in the Rx queue. */ for (i = 0; i < RX_RING_SIZE; i++) { struct sk_buff *skb = tp->rx_buffers[i].skb; @@ -803,6 +797,7 @@ static int tulip_close (struct net_device *dev) dev_kfree_skb (skb); } } + for (i = 0; i < TX_RING_SIZE; i++) { struct sk_buff *skb = tp->tx_buffers[i].skb; @@ -814,6 +809,24 @@ static int tulip_close (struct net_device *dev) tp->tx_buffers[i].skb = NULL; tp->tx_buffers[i].mapping = 0; } +} + +static int tulip_close (struct net_device *dev) +{ + struct tulip_private *tp = netdev_priv(dev); + void __iomem *ioaddr = tp->base_addr; + + netif_stop_queue (dev); + + tulip_down (dev); + + if (tulip_debug > 1) + printk (KERN_DEBUG "%s: Shutting down ethercard, status was %2.2x.\n", + dev->name, ioread32 (ioaddr + CSR5)); + + free_irq (dev->irq, dev); + + tulip_free_ring (dev); return 0; } -- cgit v1.2.3 From 0e0fde3c8d65524b8dfd834332d6e4a92711a66a Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Mon, 16 Mar 2009 19:50:57 +0000 Subject: sh_eth: Change handling of IRQ Handling of IRQ of the SH7763/SH7764 CPU which sh_eth supported was changed. This revises it for this change. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: David S. Miller --- drivers/net/sh_eth.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 7f8e514eb5e9..7b1882765a0c 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -687,6 +687,7 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) { struct net_device *ndev = netdev; struct sh_eth_private *mdp = netdev_priv(ndev); + irqreturn_t ret = IRQ_NONE; u32 ioaddr, boguscnt = RX_RING_SIZE; u32 intr_status = 0; @@ -696,7 +697,13 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) /* Get interrpt stat */ intr_status = ctrl_inl(ioaddr + EESR); /* Clear interrupt */ - ctrl_outl(intr_status, ioaddr + EESR); + if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF | + EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF | + TX_CHECK | EESR_ERR_CHECK)) { + ctrl_outl(intr_status, ioaddr + EESR); + ret = IRQ_HANDLED; + } else + goto other_irq; if (intr_status & (EESR_FRC | /* Frame recv*/ EESR_RMAF | /* Multi cast address recv*/ @@ -723,9 +730,10 @@ static irqreturn_t sh_eth_interrupt(int irq, void *netdev) ndev->name, intr_status); } +other_irq: spin_unlock(&mdp->lock); - return IRQ_HANDLED; + return ret; } static void sh_eth_timer(unsigned long data) @@ -844,7 +852,13 @@ static int sh_eth_open(struct net_device *ndev) int ret = 0; struct sh_eth_private *mdp = netdev_priv(ndev); - ret = request_irq(ndev->irq, &sh_eth_interrupt, 0, ndev->name, ndev); + ret = request_irq(ndev->irq, &sh_eth_interrupt, +#if defined(CONFIG_CPU_SUBTYPE_SH7763) || defined(CONFIG_CPU_SUBTYPE_SH7764) + IRQF_SHARED, +#else + 0, +#endif + ndev->name, ndev); if (ret) { printk(KERN_ERR "Can not assign IRQ number to %s\n", CARDNAME); return ret; -- cgit v1.2.3 From 2e2a6a9f710255c87cef670fb71fc9e74bef1da2 Mon Sep 17 00:00:00 2001 From: Nobuhiro Iwamatsu Date: Mon, 16 Mar 2009 19:52:23 +0000 Subject: sh_eth: Fix mistake of the address of SH7763 Address of SH_TSU_ADDR and ARSTR of SH7763 was wrong. This revise it. Signed-off-by: Nobuhiro Iwamatsu Signed-off-by: David S. Miller --- drivers/net/sh_eth.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sh_eth.h b/drivers/net/sh_eth.h index 73bc7181cc18..1537e13e623d 100644 --- a/drivers/net/sh_eth.h +++ b/drivers/net/sh_eth.h @@ -43,8 +43,8 @@ #define SH7763_SKB_ALIGN 32 /* Chip Base Address */ -# define SH_TSU_ADDR 0xFFE01800 -# define ARSTR 0xFFE01800 +# define SH_TSU_ADDR 0xFEE01800 +# define ARSTR SH_TSU_ADDR /* Chip Registers */ /* E-DMAC */ -- cgit v1.2.3 From 44c1d6f99d4c86638bffabf0b7a232d0fe7ae574 Mon Sep 17 00:00:00 2001 From: Steve Glendinning Date: Wed, 18 Mar 2009 23:37:18 -0700 Subject: smsc911x: reset last known duplex and carrier on open smsc911x_phy_adjust_link is called periodically by the phy layer (as it's run in polling mode), and it only updates the hardware when it sees a change in duplex or carrier. This patch clears the last known values every time the interface is brought up, instead of only when the module is loaded. Without this patch the adjust_link function never updates the hardware after an ifconfig down; ifconfig up. On a full duplex link this causes the tx error counter to increment, even though packets are correctly transmitted, as the default MAC_CR register setting is for half duplex. The tx errors are "no carrier" errors, which should be ignored in full-duplex mode. When MAC_CR is set to "full duplex" mode they are correctly ignored by the hardware. Note that even with this patch the tx error counter can increment if packets are transmitted between "ifconfig up" and the first phy poll interval. An improved solution would use the phy interrupt with phylib, but I haven't managed to make this work 100% robustly yet. Signed-off-by: Steve Glendinning Signed-off-by: David S. Miller --- drivers/net/smsc911x.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 9a78daec2fe9..d1590ac55e4b 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -1225,6 +1225,10 @@ static int smsc911x_open(struct net_device *dev) dev_info(&dev->dev, "SMSC911x/921x identified at %#08lx, IRQ: %d\n", (unsigned long)pdata->ioaddr, dev->irq); + /* Reset the last known duplex and carrier */ + pdata->last_duplex = -1; + pdata->last_carrier = -1; + /* Bring the PHY up */ phy_start(pdata->phy_dev); -- cgit v1.2.3 From 170ebf85160dd128e1c4206cc197cce7d1424705 Mon Sep 17 00:00:00 2001 From: Tilman Schmidt Date: Wed, 18 Mar 2009 23:44:23 -0700 Subject: bas_gigaset: correctly allocate USB interrupt transfer buffer Every USB transfer buffer has to be allocated individually by kmalloc. Impact: bugfix, no functional change Signed-off-by: Tilman Schmidt Tested-by: Kolja Waschk Signed-off-by: David S. Miller --- drivers/isdn/gigaset/bas-gigaset.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/isdn/gigaset/bas-gigaset.c b/drivers/isdn/gigaset/bas-gigaset.c index 18dd8aacbe8d..831ddce1467b 100644 --- a/drivers/isdn/gigaset/bas-gigaset.c +++ b/drivers/isdn/gigaset/bas-gigaset.c @@ -46,6 +46,9 @@ MODULE_PARM_DESC(cidmode, "Call-ID mode"); /* length limit according to Siemens 3070usb-protokoll.doc ch. 2.1 */ #define IF_WRITEBUF 264 +/* interrupt pipe message size according to ibid. ch. 2.2 */ +#define IP_MSGSIZE 3 + /* Values for the Gigaset 307x */ #define USB_GIGA_VENDOR_ID 0x0681 #define USB_3070_PRODUCT_ID 0x0001 @@ -110,7 +113,7 @@ struct bas_cardstate { unsigned char *rcvbuf; /* AT reply receive buffer */ struct urb *urb_int_in; /* URB for interrupt pipe */ - unsigned char int_in_buf[3]; + unsigned char *int_in_buf; spinlock_t lock; /* locks all following */ int basstate; /* bitmap (BS_*) */ @@ -657,7 +660,7 @@ static void read_int_callback(struct urb *urb) } /* drop incomplete packets even if the missing bytes wouldn't matter */ - if (unlikely(urb->actual_length < 3)) { + if (unlikely(urb->actual_length < IP_MSGSIZE)) { dev_warn(cs->dev, "incomplete interrupt packet (%d bytes)\n", urb->actual_length); goto resubmit; @@ -2127,6 +2130,7 @@ static void gigaset_reinitbcshw(struct bc_state *bcs) static void gigaset_freecshw(struct cardstate *cs) { /* timers, URBs and rcvbuf are disposed of in disconnect */ + kfree(cs->hw.bas->int_in_buf); kfree(cs->hw.bas); cs->hw.bas = NULL; } @@ -2140,6 +2144,12 @@ static int gigaset_initcshw(struct cardstate *cs) pr_err("out of memory\n"); return 0; } + ucs->int_in_buf = kmalloc(IP_MSGSIZE, GFP_KERNEL); + if (!ucs->int_in_buf) { + kfree(ucs); + pr_err("out of memory\n"); + return 0; + } ucs->urb_cmd_in = NULL; ucs->urb_cmd_out = NULL; @@ -2292,7 +2302,7 @@ static int gigaset_probe(struct usb_interface *interface, usb_fill_int_urb(ucs->urb_int_in, udev, usb_rcvintpipe(udev, (endpoint->bEndpointAddress) & 0x0f), - ucs->int_in_buf, 3, read_int_callback, cs, + ucs->int_in_buf, IP_MSGSIZE, read_int_callback, cs, endpoint->bInterval); if ((rc = usb_submit_urb(ucs->urb_int_in, GFP_KERNEL)) != 0) { dev_err(cs->dev, "could not submit interrupt URB: %s\n", -- cgit v1.2.3 From ea1dae11e0baca5d633207fe50fc3cd30a5d68ee Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Thu, 19 Mar 2009 23:56:20 -0700 Subject: be2net: replenish when posting to rx-queue is starved in out of mem conditions This is a patch to replenish the rx-queue when it is in a starved state (due to out-of-mem conditions) Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be.h | 1 + drivers/net/benet/be_main.c | 50 ++++++++++++++++++++++++++------------------- 2 files changed, 30 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index 63d593d53153..f327be57ca96 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -194,6 +194,7 @@ struct be_adapter { struct be_eq_obj rx_eq; struct be_rx_obj rx_obj; u32 big_page_size; /* Compounded page size shared by rx wrbs */ + bool rx_post_starved; /* Zero rx frags have been posted to BE */ struct vlan_group *vlan_grp; u16 num_vlans; diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 897a63de5bdb..80fe1e055d91 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -273,26 +273,6 @@ static void be_rx_eqd_update(struct be_adapter *adapter) rx_eq->cur_eqd = eqd; } -static void be_worker(struct work_struct *work) -{ - struct be_adapter *adapter = - container_of(work, struct be_adapter, work.work); - int status; - - /* Check link */ - be_link_status_update(adapter); - - /* Get Stats */ - status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); - if (!status) - netdev_stats_update(adapter); - - /* Set EQ delay */ - be_rx_eqd_update(adapter); - - schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); -} - static struct net_device_stats *be_get_stats(struct net_device *dev) { struct be_adapter *adapter = netdev_priv(dev); @@ -900,8 +880,11 @@ static void be_post_rx_frags(struct be_adapter *adapter) page_info->last_page_user = true; if (posted) { - be_rxq_notify(&adapter->ctrl, rxq->id, posted); atomic_add(posted, &rxq->used); + be_rxq_notify(&adapter->ctrl, rxq->id, posted); + } else if (atomic_read(&rxq->used) == 0) { + /* Let be_worker replenish when memory is available */ + adapter->rx_post_starved = true; } return; @@ -1305,6 +1288,31 @@ int be_poll_tx(struct napi_struct *napi, int budget) return 1; } +static void be_worker(struct work_struct *work) +{ + struct be_adapter *adapter = + container_of(work, struct be_adapter, work.work); + int status; + + /* Check link */ + be_link_status_update(adapter); + + /* Get Stats */ + status = be_cmd_get_stats(&adapter->ctrl, &adapter->stats.cmd); + if (!status) + netdev_stats_update(adapter); + + /* Set EQ delay */ + be_rx_eqd_update(adapter); + + if (adapter->rx_post_starved) { + adapter->rx_post_starved = false; + be_post_rx_frags(adapter); + } + + schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000)); +} + static void be_msix_enable(struct be_adapter *adapter) { int i, status; -- cgit v1.2.3 From 1ab1ab7543de53c945ea24140409ef67ed173eb4 Mon Sep 17 00:00:00 2001 From: Sathya Perla Date: Thu, 19 Mar 2009 23:56:46 -0700 Subject: be2net: fix to restore vlan ids into BE2 during a IF DOWN->UP cycle This is a patch to reconfigure vlan-ids during an i/f down/up cycle Signed-off-by: Sathya Perla Signed-off-by: David S. Miller --- drivers/net/benet/be_main.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index 80fe1e055d91..0ecaffb70e58 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -473,7 +473,7 @@ static int be_change_mtu(struct net_device *netdev, int new_mtu) * program them in BE. If more than BE_NUM_VLANS_SUPPORTED are configured, * set the BE in promiscuous VLAN mode. */ -static void be_vids_config(struct net_device *netdev) +static void be_vid_config(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); u16 vtag[BE_NUM_VLANS_SUPPORTED]; @@ -516,7 +516,7 @@ static void be_vlan_add_vid(struct net_device *netdev, u16 vid) adapter->num_vlans++; adapter->vlan_tag[vid] = 1; - be_vids_config(netdev); + be_vid_config(netdev); } static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) @@ -527,7 +527,7 @@ static void be_vlan_rem_vid(struct net_device *netdev, u16 vid) adapter->vlan_tag[vid] = 0; vlan_group_set_device(adapter->vlan_grp, vid, NULL); - be_vids_config(netdev); + be_vid_config(netdev); } static void be_set_multicast_filter(struct net_device *netdev) @@ -1430,6 +1430,8 @@ static int be_open(struct net_device *netdev) if (status != 0) goto do_none; + be_vid_config(netdev); + status = be_cmd_set_flow_control(ctrl, true, true); if (status != 0) goto if_destroy; @@ -1864,8 +1866,6 @@ static int be_resume(struct pci_dev *pdev) pci_set_power_state(pdev, 0); pci_restore_state(pdev); - be_vids_config(netdev); - if (netif_running(netdev)) { rtnl_lock(); be_open(netdev); -- cgit v1.2.3 From 5ed0102fbf36f58091089907213b4bd191ca2e0c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 19 Mar 2009 23:58:01 -0700 Subject: sungem: missing net_device_ops Sungem driver only got partially converted to net_device_ops. Since this could cause bugs, please push this to 2.6.29 Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- drivers/net/sungem.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sungem.c b/drivers/net/sungem.c index 0fcb7503363d..c9c7650826c0 100644 --- a/drivers/net/sungem.c +++ b/drivers/net/sungem.c @@ -2998,8 +2998,11 @@ static const struct net_device_ops gem_netdev_ops = { .ndo_do_ioctl = gem_ioctl, .ndo_tx_timeout = gem_tx_timeout, .ndo_change_mtu = gem_change_mtu, - .ndo_set_mac_address = eth_mac_addr, .ndo_validate_addr = eth_validate_addr, + .ndo_set_mac_address = gem_set_mac_address, +#ifdef CONFIG_NET_POLL_CONTROLLER + .ndo_poll_controller = gem_poll_controller, +#endif }; static int __devinit gem_init_one(struct pci_dev *pdev, @@ -3161,10 +3164,6 @@ static int __devinit gem_init_one(struct pci_dev *pdev, dev->watchdog_timeo = 5 * HZ; dev->irq = pdev->irq; dev->dma = 0; - dev->set_mac_address = gem_set_mac_address; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = gem_poll_controller; -#endif /* Set that now, in case PM kicks in now */ pci_set_drvdata(pdev, dev); -- cgit v1.2.3 From e2fc4d19292ef2eb208f76976ddc3320cc5839b6 Mon Sep 17 00:00:00 2001 From: Maciej Sosnowski Date: Sat, 21 Mar 2009 13:31:23 -0700 Subject: dca: add missing copyright/license headers In two dca files copyright and license headers are missing. This patch adds them there. Signed-off-by: Maciej Sosnowski Signed-off-by: David S. Miller --- drivers/dca/dca-sysfs.c | 21 +++++++++++++++++++++ include/linux/dca.h | 20 ++++++++++++++++++++ 2 files changed, 41 insertions(+) (limited to 'drivers') diff --git a/drivers/dca/dca-sysfs.c b/drivers/dca/dca-sysfs.c index bb538b9690e0..ee916c9857ee 100644 --- a/drivers/dca/dca-sysfs.c +++ b/drivers/dca/dca-sysfs.c @@ -1,3 +1,24 @@ +/* + * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. + * + * 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., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ + #include #include #include diff --git a/include/linux/dca.h b/include/linux/dca.h index b00a753eda53..9c20c7e87d0a 100644 --- a/include/linux/dca.h +++ b/include/linux/dca.h @@ -1,3 +1,23 @@ +/* + * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. + * + * 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., 59 + * Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The full GNU General Public License is included in this distribution in the + * file called COPYING. + */ #ifndef DCA_H #define DCA_H /* DCA Provider API */ -- cgit v1.2.3 From 4b97926ddf51b3919c859e2086fef3c8c3c46c61 Mon Sep 17 00:00:00 2001 From: Ilya Yanok Date: Sat, 21 Mar 2009 16:58:47 -0700 Subject: dnet: DNET should depend on HAS_IOMEM Signed-off-by: Ilya Yanok Signed-off-by: David S. Miller --- drivers/net/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 435e2e3a82c8..62d732a886f1 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1042,7 +1042,7 @@ config NI65 config DNET tristate "Dave ethernet support (DNET)" - depends on NET_ETHERNET + depends on NET_ETHERNET && HAS_IOMEM select PHYLIB help The Dave ethernet interface (DNET) is found on Qong Board FPGA. -- cgit v1.2.3 From 18a0d89e54ca0f6f33582f99ae39867b2c975559 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 20 Mar 2009 09:22:30 +1100 Subject: radeonfb: Whack the PCI PM register until it sticks This fixes a regression introduced when we switched to using the core pci_set_power_state(). The chip seems to need the state to be written over and over again until it sticks, so we do that. Note that the code is a bit blunt, without timeout, etc... but that's pretty much because I put back in there the code exactly as it used to be before the regression. I still add a call to pci_set_power_state() at the end so that ACPI gets called appropriately on x86. Signed-off-by: Benjamin Herrenschmidt Tested-by: Raymond Wooninck Acked-by: Rafael J. Wysocki Cc: Jesse Barnes Cc: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/aty/radeon_pm.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 81603f85e17e..c6d7cc76516f 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -2507,6 +2507,25 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) #endif /* CONFIG_PPC_OF */ +static void radeonfb_whack_power_state(struct radeonfb_info *rinfo, pci_power_t state) +{ + u16 pwr_cmd; + + for (;;) { + pci_read_config_word(rinfo->pdev, + rinfo->pm_reg+PCI_PM_CTRL, + &pwr_cmd); + if (pwr_cmd & 2) + break; + pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2; + pci_write_config_word(rinfo->pdev, + rinfo->pm_reg+PCI_PM_CTRL, + pwr_cmd); + msleep(500); + } + rinfo->pdev->current_state = state; +} + static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) { u32 tmp; @@ -2558,6 +2577,11 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) /* Switch PCI power management to D2. */ pci_disable_device(rinfo->pdev); pci_save_state(rinfo->pdev); + /* The chip seems to need us to whack the PM register + * repeatedly until it sticks. We do that -prior- to + * calling pci_set_power_state() + */ + radeonfb_whack_power_state(rinfo, PCI_D2); pci_set_power_state(rinfo->pdev, PCI_D2); } else { printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n", -- cgit v1.2.3 From 6580f57d485f70851218813fa053d971915f61fb Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Sun, 22 Mar 2009 21:22:48 -0700 Subject: net: update dnet.c for bus_id removal Signed-off-by: Stephen Rothwell Signed-off-by: David S. Miller --- drivers/net/dnet.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dnet.c b/drivers/net/dnet.c index 5c347f70cb67..1b4063222a82 100644 --- a/drivers/net/dnet.c +++ b/drivers/net/dnet.c @@ -280,11 +280,11 @@ static int dnet_mii_probe(struct net_device *dev) /* attach the mac to the phy */ if (bp->capabilities & DNET_HAS_RMII) { - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &dnet_handle_link_change, 0, PHY_INTERFACE_MODE_RMII); } else { - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &dnet_handle_link_change, 0, PHY_INTERFACE_MODE_MII); } @@ -927,7 +927,7 @@ static int __devinit dnet_probe(struct platform_device *pdev) phydev = bp->phy_dev; dev_info(&pdev->dev, "attached PHY driver [%s] " "(mii_bus:phy_addr=%s, irq=%d)\n", - phydev->drv->name, phydev->dev.bus_id, phydev->irq); + phydev->drv->name, dev_name(&phydev->dev), phydev->irq); return 0; -- cgit v1.2.3 From e3162d381fc359ebe5c98a3e216888a7cb200051 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Sun, 22 Mar 2009 21:28:39 -0700 Subject: dm9000: locking bugfix This fixes a locking bug in the dm9000 driver. It calls request_irq() without setting IRQF_DISABLED ... which is correct for handlers that support IRQ sharing, since that behavior is not guaranteed for shared IRQs. However, its IRQ handler then wrongly assumes that IRQs are blocked. So the fix just uses the right spinlock primitives in the IRQ handler. NOTE: this is a classic example of the type of bug which lockdep currently masks by forcibly setting IRQF_DISABLED on IRQ handlers that did not request that flag. Signed-off-by: David Brownell Signed-off-by: David S. Miller --- drivers/net/dm9000.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index bcf92917bbf3..254ec62b5f58 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -930,13 +930,15 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id) struct net_device *dev = dev_id; board_info_t *db = netdev_priv(dev); int int_status; + unsigned long flags; u8 reg_save; dm9000_dbg(db, 3, "entering %s\n", __func__); /* A real interrupt coming */ - spin_lock(&db->lock); + /* holders of db->lock must always block IRQs */ + spin_lock_irqsave(&db->lock, flags); /* Save previous register address */ reg_save = readb(db->io_addr); @@ -972,7 +974,7 @@ static irqreturn_t dm9000_interrupt(int irq, void *dev_id) /* Restore previous register address */ writeb(reg_save, db->io_addr); - spin_unlock(&db->lock); + spin_unlock_irqrestore(&db->lock, flags); return IRQ_HANDLED; } -- cgit v1.2.3 From 61fa9dcf9329cb92c220f7b656410fbe5e72f933 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Sun, 22 Mar 2009 21:30:52 -0700 Subject: ucc_geth: Fix oops when using fixed-link support commit b1c4a9dddf09fe99b8f88252718ac5b357363dc4 ("ucc_geth: Change uec phy id to the same format as gianfar's") introduced a regression in the ucc_geth driver that causes this oops when fixed-link is used: Unable to handle kernel paging request for data at address 0x00000000 Faulting instruction address: 0xc0151270 Oops: Kernel access of bad area, sig: 11 [#1] TMCUTU NIP: c0151270 LR: c0151270 CTR: c0017760 REGS: cf81fa60 TRAP: 0300 Not tainted (2.6.29-rc8) MSR: 00009032 CR: 24024042 XER: 20000000 DAR: 00000000, DSISR: 20000000 TASK = cf81cba0[1] 'swapper' THREAD: cf81e000 GPR00: c0151270 cf81fb10 cf81cba0 00000000 c0272e20 c025f354 00001e80 cf86b08c GPR08: d1068200 cffffb74 06000000 d106c200 42024042 10085148 0fffd000 0ffc81a0 GPR16: 00000001 00000001 00000000 007ffeb0 00000000 0000c000 cf83f36c cf83f000 GPR24: 00000030 cf83f360 cf81fb20 00000000 d106c200 20000000 00001e80 cf83f360 NIP [c0151270] ucc_geth_open+0x330/0x1efc LR [c0151270] ucc_geth_open+0x330/0x1efc Call Trace: [cf81fb10] [c0151270] ucc_geth_open+0x330/0x1efc (unreliable) [cf81fba0] [c0187638] dev_open+0xbc/0x12c [cf81fbc0] [c0187e38] dev_change_flags+0x8c/0x1b0 This patch fixes the issue by removing offending (and somewhat duplicate) code from init_phy() routine, and changes _probe() function to use uec_mdio_bus_name(). Also, since we fully construct phy_bus_id in the _probe() routine, we no longer need ->phy_address and ->mdio_bus fields in ucc_geth_info structure. I wish the patch would be a bit shorter, but it seems like the only way to fix the issue in a sane way. Luckily, the patch has been tested with real PHYs and fixed-link, so no further regressions expected. Reported-by: Joakim Tjernlund Signed-off-by: Anton Vorontsov Tested-by: Joakim Tjernlund Signed-off-by: David S. Miller --- drivers/net/ucc_geth.c | 34 ++++++++++------------------------ drivers/net/ucc_geth.h | 3 +-- 2 files changed, 11 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index e87986867ba5..1f61e42c641d 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -1536,32 +1536,15 @@ static void adjust_link(struct net_device *dev) static int init_phy(struct net_device *dev) { struct ucc_geth_private *priv = netdev_priv(dev); - struct device_node *np = priv->node; - struct device_node *phy, *mdio; - const phandle *ph; - char bus_name[MII_BUS_ID_SIZE]; - const unsigned int *id; + struct ucc_geth_info *ug_info = priv->ug_info; struct phy_device *phydev; - char phy_id[BUS_ID_SIZE]; priv->oldlink = 0; priv->oldspeed = 0; priv->oldduplex = -1; - ph = of_get_property(np, "phy-handle", NULL); - phy = of_find_node_by_phandle(*ph); - mdio = of_get_parent(phy); - - id = of_get_property(phy, "reg", NULL); - - of_node_put(phy); - of_node_put(mdio); - - uec_mdio_bus_name(bus_name, mdio); - snprintf(phy_id, sizeof(phy_id), "%s:%02x", - bus_name, *id); - - phydev = phy_connect(dev, phy_id, &adjust_link, 0, priv->phy_interface); + phydev = phy_connect(dev, ug_info->phy_bus_id, &adjust_link, 0, + priv->phy_interface); if (IS_ERR(phydev)) { printk("%s: Could not attach to PHY\n", dev->name); @@ -3629,10 +3612,12 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma ug_info->uf_info.irq = irq_of_parse_and_map(np, 0); fixed_link = of_get_property(np, "fixed-link", NULL); if (fixed_link) { - snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "0"); - ug_info->phy_address = fixed_link[0]; + snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), + PHY_ID_FMT, "0", fixed_link[0]); phy = NULL; } else { + char bus_name[MII_BUS_ID_SIZE]; + ph = of_get_property(np, "phy-handle", NULL); phy = of_find_node_by_phandle(*ph); @@ -3643,7 +3628,6 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma prop = of_get_property(phy, "reg", NULL); if (prop == NULL) return -1; - ug_info->phy_address = *prop; /* Set the bus id */ mdio = of_get_parent(phy); @@ -3657,7 +3641,9 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma if (err) return -1; - snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "%x", res.start); + uec_mdio_bus_name(bus_name, mdio); + snprintf(ug_info->phy_bus_id, sizeof(ug_info->phy_bus_id), + "%s:%02x", bus_name, *prop); } /* get the phy interface type, or default to MII */ diff --git a/drivers/net/ucc_geth.h b/drivers/net/ucc_geth.h index 16cbe42ba43c..611bdef2402b 100644 --- a/drivers/net/ucc_geth.h +++ b/drivers/net/ucc_geth.h @@ -1091,8 +1091,7 @@ struct ucc_geth_info { u32 eventRegMask; u16 pausePeriod; u16 extensionField; - u8 phy_address; - char mdio_bus[MII_BUS_ID_SIZE]; + char phy_bus_id[BUS_ID_SIZE]; u8 weightfactor[NUM_TX_QUEUES]; u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES]; u8 l2qt[UCC_GETH_VLAN_PRIORITY_MAX]; -- cgit v1.2.3