diff options
190 files changed, 5370 insertions, 1341 deletions
diff --git a/.gitignore b/.gitignore index fdcce40226d7..3016ed30526d 100644 --- a/.gitignore +++ b/.gitignore | |||
| @@ -27,6 +27,7 @@ TAGS | |||
| 27 | vmlinux* | 27 | vmlinux* |
| 28 | !vmlinux.lds.S | 28 | !vmlinux.lds.S |
| 29 | System.map | 29 | System.map |
| 30 | Module.markers | ||
| 30 | Module.symvers | 31 | Module.symvers |
| 31 | !.gitignore | 32 | !.gitignore |
| 32 | 33 | ||
diff --git a/Documentation/ABI/stable/sysfs-class-ubi b/Documentation/ABI/stable/sysfs-class-ubi new file mode 100644 index 000000000000..18d471d9faea --- /dev/null +++ b/Documentation/ABI/stable/sysfs-class-ubi | |||
| @@ -0,0 +1,212 @@ | |||
| 1 | What: /sys/class/ubi/ | ||
| 2 | Date: July 2006 | ||
| 3 | KernelVersion: 2.6.22 | ||
| 4 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 5 | Description: | ||
| 6 | The ubi/ class sub-directory belongs to the UBI subsystem and | ||
| 7 | provides general UBI information, per-UBI device information | ||
| 8 | and per-UBI volume information. | ||
| 9 | |||
| 10 | What: /sys/class/ubi/version | ||
| 11 | Date: July 2006 | ||
| 12 | KernelVersion: 2.6.22 | ||
| 13 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 14 | Description: | ||
| 15 | This file contains version of the latest supported UBI on-media | ||
| 16 | format. Currently it is 1, and there is no plan to change this. | ||
| 17 | However, if in the future UBI needs on-flash format changes | ||
| 18 | which cannot be done in a compatible manner, a new format | ||
| 19 | version will be added. So this is a mechanism for possible | ||
| 20 | future backward-compatible (but forward-incompatible) | ||
| 21 | improvements. | ||
| 22 | |||
| 23 | What: /sys/class/ubiX/ | ||
| 24 | Date: July 2006 | ||
| 25 | KernelVersion: 2.6.22 | ||
| 26 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 27 | Description: | ||
| 28 | The /sys/class/ubi0, /sys/class/ubi1, etc directories describe | ||
| 29 | UBI devices (UBI device 0, 1, etc). They contain general UBI | ||
| 30 | device information and per UBI volume information (each UBI | ||
| 31 | device may have many UBI volumes) | ||
| 32 | |||
| 33 | What: /sys/class/ubi/ubiX/avail_eraseblocks | ||
| 34 | Date: July 2006 | ||
| 35 | KernelVersion: 2.6.22 | ||
| 36 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 37 | Description: | ||
| 38 | Amount of available logical eraseblock. For example, one may | ||
| 39 | create a new UBI volume which has this amount of logical | ||
| 40 | eraseblocks. | ||
| 41 | |||
| 42 | What: /sys/class/ubi/ubiX/bad_peb_count | ||
| 43 | Date: July 2006 | ||
| 44 | KernelVersion: 2.6.22 | ||
| 45 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 46 | Description: | ||
| 47 | Count of bad physical eraseblocks on the underlying MTD device. | ||
| 48 | |||
| 49 | What: /sys/class/ubi/ubiX/bgt_enabled | ||
| 50 | Date: July 2006 | ||
| 51 | KernelVersion: 2.6.22 | ||
| 52 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 53 | Description: | ||
| 54 | Contains ASCII "0\n" if the UBI background thread is disabled, | ||
| 55 | and ASCII "1\n" if it is enabled. | ||
| 56 | |||
| 57 | What: /sys/class/ubi/ubiX/dev | ||
| 58 | Date: July 2006 | ||
| 59 | KernelVersion: 2.6.22 | ||
| 60 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 61 | Description: | ||
| 62 | Major and minor numbers of the character device corresponding | ||
| 63 | to this UBI device (in <major>:<minor> format). | ||
| 64 | |||
| 65 | What: /sys/class/ubi/ubiX/eraseblock_size | ||
| 66 | Date: July 2006 | ||
| 67 | KernelVersion: 2.6.22 | ||
| 68 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 69 | Description: | ||
| 70 | Maximum logical eraseblock size this UBI device may provide. UBI | ||
| 71 | volumes may have smaller logical eraseblock size because of their | ||
| 72 | alignment. | ||
| 73 | |||
| 74 | What: /sys/class/ubi/ubiX/max_ec | ||
| 75 | Date: July 2006 | ||
| 76 | KernelVersion: 2.6.22 | ||
| 77 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 78 | Description: | ||
| 79 | Maximum physical eraseblock erase counter value. | ||
| 80 | |||
| 81 | What: /sys/class/ubi/ubiX/max_vol_count | ||
| 82 | Date: July 2006 | ||
| 83 | KernelVersion: 2.6.22 | ||
| 84 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 85 | Description: | ||
| 86 | Maximum number of volumes which this UBI device may have. | ||
| 87 | |||
| 88 | What: /sys/class/ubi/ubiX/min_io_size | ||
| 89 | Date: July 2006 | ||
| 90 | KernelVersion: 2.6.22 | ||
| 91 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 92 | Description: | ||
| 93 | Minimum input/output unit size. All the I/O may only be done | ||
| 94 | in fractions of the contained number. | ||
| 95 | |||
| 96 | What: /sys/class/ubi/ubiX/mtd_num | ||
| 97 | Date: January 2008 | ||
| 98 | KernelVersion: 2.6.25 | ||
| 99 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 100 | Description: | ||
| 101 | Number of the underlying MTD device. | ||
| 102 | |||
| 103 | What: /sys/class/ubi/ubiX/reserved_for_bad | ||
| 104 | Date: July 2006 | ||
| 105 | KernelVersion: 2.6.22 | ||
| 106 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 107 | Description: | ||
| 108 | Number of physical eraseblocks reserved for bad block handling. | ||
| 109 | |||
| 110 | What: /sys/class/ubi/ubiX/total_eraseblocks | ||
| 111 | Date: July 2006 | ||
| 112 | KernelVersion: 2.6.22 | ||
| 113 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 114 | Description: | ||
| 115 | Total number of good (not marked as bad) physical eraseblocks on | ||
| 116 | the underlying MTD device. | ||
| 117 | |||
| 118 | What: /sys/class/ubi/ubiX/volumes_count | ||
| 119 | Date: July 2006 | ||
| 120 | KernelVersion: 2.6.22 | ||
| 121 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 122 | Description: | ||
| 123 | Count of volumes on this UBI device. | ||
| 124 | |||
| 125 | What: /sys/class/ubi/ubiX/ubiX_Y/ | ||
| 126 | Date: July 2006 | ||
| 127 | KernelVersion: 2.6.22 | ||
| 128 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 129 | Description: | ||
| 130 | The /sys/class/ubi/ubiX/ubiX_0/, /sys/class/ubi/ubiX/ubiX_1/, | ||
| 131 | etc directories describe UBI volumes on UBI device X (volumes | ||
| 132 | 0, 1, etc). | ||
| 133 | |||
| 134 | What: /sys/class/ubi/ubiX/ubiX_Y/alignment | ||
| 135 | Date: July 2006 | ||
| 136 | KernelVersion: 2.6.22 | ||
| 137 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 138 | Description: | ||
| 139 | Volume alignment - the value the logical eraseblock size of | ||
| 140 | this volume has to be aligned on. For example, 2048 means that | ||
| 141 | logical eraseblock size is multiple of 2048. In other words, | ||
| 142 | volume logical eraseblock size is UBI device logical eraseblock | ||
| 143 | size aligned to the alignment value. | ||
| 144 | |||
| 145 | What: /sys/class/ubi/ubiX/ubiX_Y/corrupted | ||
| 146 | Date: July 2006 | ||
| 147 | KernelVersion: 2.6.22 | ||
| 148 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 149 | Description: | ||
| 150 | Contains ASCII "0\n" if the UBI volume is OK, and ASCII "1\n" | ||
| 151 | if it is corrupted (e.g., due to an interrupted volume update). | ||
| 152 | |||
| 153 | What: /sys/class/ubi/ubiX/ubiX_Y/data_bytes | ||
| 154 | Date: July 2006 | ||
| 155 | KernelVersion: 2.6.22 | ||
| 156 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 157 | Description: | ||
| 158 | The amount of data this volume contains. This value makes sense | ||
| 159 | only for static volumes, and for dynamic volume it equivalent | ||
| 160 | to the total volume size in bytes. | ||
| 161 | |||
| 162 | What: /sys/class/ubi/ubiX/ubiX_Y/dev | ||
| 163 | Date: July 2006 | ||
| 164 | KernelVersion: 2.6.22 | ||
| 165 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 166 | Description: | ||
| 167 | Major and minor numbers of the character device corresponding | ||
| 168 | to this UBI volume (in <major>:<minor> format). | ||
| 169 | |||
| 170 | What: /sys/class/ubi/ubiX/ubiX_Y/name | ||
| 171 | Date: July 2006 | ||
| 172 | KernelVersion: 2.6.22 | ||
| 173 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 174 | Description: | ||
| 175 | Volume name. | ||
| 176 | |||
| 177 | What: /sys/class/ubi/ubiX/ubiX_Y/reserved_ebs | ||
| 178 | Date: July 2006 | ||
| 179 | KernelVersion: 2.6.22 | ||
| 180 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 181 | Description: | ||
| 182 | Count of physical eraseblock reserved for this volume. | ||
| 183 | Equivalent to the volume size in logical eraseblocks. | ||
| 184 | |||
| 185 | What: /sys/class/ubi/ubiX/ubiX_Y/type | ||
| 186 | Date: July 2006 | ||
| 187 | KernelVersion: 2.6.22 | ||
| 188 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 189 | Description: | ||
| 190 | Volume type. Contains ASCII "dynamic\n" for dynamic volumes and | ||
| 191 | "static\n" for static volumes. | ||
| 192 | |||
| 193 | What: /sys/class/ubi/ubiX/ubiX_Y/upd_marker | ||
| 194 | Date: July 2006 | ||
| 195 | KernelVersion: 2.6.22 | ||
| 196 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 197 | Description: | ||
| 198 | Contains ASCII "0\n" if the update marker is not set for this | ||
| 199 | volume, and "1\n" if it is set. The update marker is set when | ||
| 200 | volume update starts, and cleaned when it ends. So the presence | ||
| 201 | of the update marker indicates that the volume is being updated | ||
| 202 | at the moment of the update was interrupted. The later may be | ||
| 203 | checked using the "corrupted" sysfs file. | ||
| 204 | |||
| 205 | What: /sys/class/ubi/ubiX/ubiX_Y/usable_eb_size | ||
| 206 | Date: July 2006 | ||
| 207 | KernelVersion: 2.6.22 | ||
| 208 | Contact: Artem Bityutskiy <dedekind@infradead.org> | ||
| 209 | Description: | ||
| 210 | Logical eraseblock size of this volume. Equivalent to logical | ||
| 211 | eraseblock size of the device aligned on the volume alignment | ||
| 212 | value. | ||
diff --git a/Documentation/HOWTO b/Documentation/HOWTO index 54835610b3d6..0291ade44c17 100644 --- a/Documentation/HOWTO +++ b/Documentation/HOWTO | |||
| @@ -249,9 +249,11 @@ process is as follows: | |||
| 249 | release a new -rc kernel every week. | 249 | release a new -rc kernel every week. |
| 250 | - Process continues until the kernel is considered "ready", the | 250 | - Process continues until the kernel is considered "ready", the |
| 251 | process should last around 6 weeks. | 251 | process should last around 6 weeks. |
| 252 | - A list of known regressions present in each -rc release is | 252 | - Known regressions in each release are periodically posted to the |
| 253 | tracked at the following URI: | 253 | linux-kernel mailing list. The goal is to reduce the length of |
| 254 | http://kernelnewbies.org/known_regressions | 254 | that list to zero before declaring the kernel to be "ready," but, in |
| 255 | the real world, a small number of regressions often remain at | ||
| 256 | release time. | ||
| 255 | 257 | ||
| 256 | It is worth mentioning what Andrew Morton wrote on the linux-kernel | 258 | It is worth mentioning what Andrew Morton wrote on the linux-kernel |
| 257 | mailing list about kernel releases: | 259 | mailing list about kernel releases: |
| @@ -261,7 +263,7 @@ mailing list about kernel releases: | |||
| 261 | 263 | ||
| 262 | 2.6.x.y -stable kernel tree | 264 | 2.6.x.y -stable kernel tree |
| 263 | --------------------------- | 265 | --------------------------- |
| 264 | Kernels with 4 digit versions are -stable kernels. They contain | 266 | Kernels with 4-part versions are -stable kernels. They contain |
| 265 | relatively small and critical fixes for security problems or significant | 267 | relatively small and critical fixes for security problems or significant |
| 266 | regressions discovered in a given 2.6.x kernel. | 268 | regressions discovered in a given 2.6.x kernel. |
| 267 | 269 | ||
| @@ -273,7 +275,10 @@ If no 2.6.x.y kernel is available, then the highest numbered 2.6.x | |||
| 273 | kernel is the current stable kernel. | 275 | kernel is the current stable kernel. |
| 274 | 276 | ||
| 275 | 2.6.x.y are maintained by the "stable" team <stable@kernel.org>, and are | 277 | 2.6.x.y are maintained by the "stable" team <stable@kernel.org>, and are |
| 276 | released almost every other week. | 278 | released as needs dictate. The normal release period is approximately |
| 279 | two weeks, but it can be longer if there are no pressing problems. A | ||
| 280 | security-related problem, instead, can cause a release to happen almost | ||
| 281 | instantly. | ||
| 277 | 282 | ||
| 278 | The file Documentation/stable_kernel_rules.txt in the kernel tree | 283 | The file Documentation/stable_kernel_rules.txt in the kernel tree |
| 279 | documents what kinds of changes are acceptable for the -stable tree, and | 284 | documents what kinds of changes are acceptable for the -stable tree, and |
| @@ -298,7 +303,9 @@ a while Andrew or the subsystem maintainer pushes it on to Linus for | |||
| 298 | inclusion in mainline. | 303 | inclusion in mainline. |
| 299 | 304 | ||
| 300 | It is heavily encouraged that all new patches get tested in the -mm tree | 305 | It is heavily encouraged that all new patches get tested in the -mm tree |
| 301 | before they are sent to Linus for inclusion in the main kernel tree. | 306 | before they are sent to Linus for inclusion in the main kernel tree. Code |
| 307 | which does not make an appearance in -mm before the opening of the merge | ||
| 308 | window will prove hard to merge into the mainline. | ||
| 302 | 309 | ||
| 303 | These kernels are not appropriate for use on systems that are supposed | 310 | These kernels are not appropriate for use on systems that are supposed |
| 304 | to be stable and they are more risky to run than any of the other | 311 | to be stable and they are more risky to run than any of the other |
| @@ -354,11 +361,12 @@ Here is a list of some of the different kernel trees available: | |||
| 354 | - SCSI, James Bottomley <James.Bottomley@SteelEye.com> | 361 | - SCSI, James Bottomley <James.Bottomley@SteelEye.com> |
| 355 | git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git | 362 | git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git |
| 356 | 363 | ||
| 364 | - x86, Ingo Molnar <mingo@elte.hu> | ||
| 365 | git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git | ||
| 366 | |||
| 357 | quilt trees: | 367 | quilt trees: |
| 358 | - USB, PCI, Driver Core, and I2C, Greg Kroah-Hartman <gregkh@suse.de> | 368 | - USB, Driver Core, and I2C, Greg Kroah-Hartman <gregkh@suse.de> |
| 359 | kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ | 369 | kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ |
| 360 | - x86-64, partly i386, Andi Kleen <ak@suse.de> | ||
| 361 | ftp.firstfloor.org:/pub/ak/x86_64/quilt/ | ||
| 362 | 370 | ||
| 363 | Other kernel trees can be found listed at http://git.kernel.org/ and in | 371 | Other kernel trees can be found listed at http://git.kernel.org/ and in |
| 364 | the MAINTAINERS file. | 372 | the MAINTAINERS file. |
| @@ -392,8 +400,8 @@ If you want to be advised of the future bug reports, you can subscribe to the | |||
| 392 | bugme-new mailing list (only new bug reports are mailed here) or to the | 400 | bugme-new mailing list (only new bug reports are mailed here) or to the |
| 393 | bugme-janitor mailing list (every change in the bugzilla is mailed here) | 401 | bugme-janitor mailing list (every change in the bugzilla is mailed here) |
| 394 | 402 | ||
| 395 | http://lists.osdl.org/mailman/listinfo/bugme-new | 403 | http://lists.linux-foundation.org/mailman/listinfo/bugme-new |
| 396 | http://lists.osdl.org/mailman/listinfo/bugme-janitors | 404 | http://lists.linux-foundation.org/mailman/listinfo/bugme-janitors |
| 397 | 405 | ||
| 398 | 406 | ||
| 399 | 407 | ||
diff --git a/Documentation/arm/Samsung-S3C24XX/NAND.txt b/Documentation/arm/Samsung-S3C24XX/NAND.txt new file mode 100644 index 000000000000..bc478a3409b8 --- /dev/null +++ b/Documentation/arm/Samsung-S3C24XX/NAND.txt | |||
| @@ -0,0 +1,30 @@ | |||
| 1 | S3C24XX NAND Support | ||
| 2 | ==================== | ||
| 3 | |||
| 4 | Introduction | ||
| 5 | ------------ | ||
| 6 | |||
| 7 | Small Page NAND | ||
| 8 | --------------- | ||
| 9 | |||
| 10 | The driver uses a 512 byte (1 page) ECC code for this setup. The | ||
| 11 | ECC code is not directly compatible with the default kernel ECC | ||
| 12 | code, so the driver enforces its own OOB layout and ECC parameters | ||
| 13 | |||
| 14 | Large Page NAND | ||
| 15 | --------------- | ||
| 16 | |||
| 17 | The driver is capable of handling NAND flash with a 2KiB page | ||
| 18 | size, with support for hardware ECC generation and correction. | ||
| 19 | |||
| 20 | Unlike the 512byte page mode, the driver generates ECC data for | ||
| 21 | each 256 byte block in an 2KiB page. This means that more than | ||
| 22 | one error in a page can be rectified. It also means that the | ||
| 23 | OOB layout remains the default kernel layout for these flashes. | ||
| 24 | |||
| 25 | |||
| 26 | Document Author | ||
| 27 | --------------- | ||
| 28 | |||
| 29 | Ben Dooks, Copyright 2007 Simtec Electronics | ||
| 30 | |||
diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt index c31b76fa66c4..d04e1e30c47f 100644 --- a/Documentation/arm/Samsung-S3C24XX/Overview.txt +++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt | |||
| @@ -156,6 +156,8 @@ NAND | |||
| 156 | controller. If there are any problems the latest linux-mtd | 156 | controller. If there are any problems the latest linux-mtd |
| 157 | code can be found from http://www.linux-mtd.infradead.org/ | 157 | code can be found from http://www.linux-mtd.infradead.org/ |
| 158 | 158 | ||
| 159 | For more information see Documentation/arm/Samsung-S3C24XX/NAND.txt | ||
| 160 | |||
| 159 | 161 | ||
| 160 | Serial | 162 | Serial |
| 161 | ------ | 163 | ------ |
diff --git a/Documentation/filesystems/nfs-rdma.txt b/Documentation/filesystems/nfs-rdma.txt index 1ae34879574b..d0ec45ae4e7d 100644 --- a/Documentation/filesystems/nfs-rdma.txt +++ b/Documentation/filesystems/nfs-rdma.txt | |||
| @@ -5,7 +5,7 @@ | |||
| 5 | ################################################################################ | 5 | ################################################################################ |
| 6 | 6 | ||
| 7 | Author: NetApp and Open Grid Computing | 7 | Author: NetApp and Open Grid Computing |
| 8 | Date: February 25, 2008 | 8 | Date: April 15, 2008 |
| 9 | 9 | ||
| 10 | Table of Contents | 10 | Table of Contents |
| 11 | ~~~~~~~~~~~~~~~~~ | 11 | ~~~~~~~~~~~~~~~~~ |
| @@ -197,12 +197,16 @@ NFS/RDMA Setup | |||
| 197 | - On the server system, configure the /etc/exports file and | 197 | - On the server system, configure the /etc/exports file and |
| 198 | start the NFS/RDMA server. | 198 | start the NFS/RDMA server. |
| 199 | 199 | ||
| 200 | Exports entries with the following format have been tested: | 200 | Exports entries with the following formats have been tested: |
| 201 | 201 | ||
| 202 | /vol0 10.97.103.47(rw,async) 192.168.0.47(rw,async,insecure,no_root_squash) | 202 | /vol0 192.168.0.47(fsid=0,rw,async,insecure,no_root_squash) |
| 203 | /vol0 192.168.0.0/255.255.255.0(fsid=0,rw,async,insecure,no_root_squash) | ||
| 203 | 204 | ||
| 204 | Here the first IP address is the client's Ethernet address and the second | 205 | The IP address(es) is(are) the client's IPoIB address for an InfiniBand HCA or the |
| 205 | IP address is the clients IPoIB address. | 206 | cleint's iWARP address(es) for an RNIC. |
| 207 | |||
| 208 | NOTE: The "insecure" option must be used because the NFS/RDMA client does not | ||
| 209 | use a reserved port. | ||
| 206 | 210 | ||
| 207 | Each time a machine boots: | 211 | Each time a machine boots: |
| 208 | 212 | ||
diff --git a/Documentation/filesystems/seq_file.txt b/Documentation/filesystems/seq_file.txt index 7fb8e6dc62bf..b843743aa0b5 100644 --- a/Documentation/filesystems/seq_file.txt +++ b/Documentation/filesystems/seq_file.txt | |||
| @@ -122,8 +122,7 @@ stop() is the place to free it. | |||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | Finally, the show() function should format the object currently pointed to | 124 | Finally, the show() function should format the object currently pointed to |
| 125 | by the iterator for output. It should return zero, or an error code if | 125 | by the iterator for output. The example module's show() function is: |
| 126 | something goes wrong. The example module's show() function is: | ||
| 127 | 126 | ||
| 128 | static int ct_seq_show(struct seq_file *s, void *v) | 127 | static int ct_seq_show(struct seq_file *s, void *v) |
| 129 | { | 128 | { |
| @@ -132,6 +131,12 @@ something goes wrong. The example module's show() function is: | |||
| 132 | return 0; | 131 | return 0; |
| 133 | } | 132 | } |
| 134 | 133 | ||
| 134 | If all is well, the show() function should return zero. A negative error | ||
| 135 | code in the usual manner indicates that something went wrong; it will be | ||
| 136 | passed back to user space. This function can also return SEQ_SKIP, which | ||
| 137 | causes the current item to be skipped; if the show() function has already | ||
| 138 | generated output before returning SEQ_SKIP, that output will be dropped. | ||
| 139 | |||
| 135 | We will look at seq_printf() in a moment. But first, the definition of the | 140 | We will look at seq_printf() in a moment. But first, the definition of the |
| 136 | seq_file iterator is finished by creating a seq_operations structure with | 141 | seq_file iterator is finished by creating a seq_operations structure with |
| 137 | the four functions we have just defined: | 142 | the four functions we have just defined: |
| @@ -182,12 +187,18 @@ The first two output a single character and a string, just like one would | |||
| 182 | expect. seq_escape() is like seq_puts(), except that any character in s | 187 | expect. seq_escape() is like seq_puts(), except that any character in s |
| 183 | which is in the string esc will be represented in octal form in the output. | 188 | which is in the string esc will be represented in octal form in the output. |
| 184 | 189 | ||
| 185 | There is also a function for printing filenames: | 190 | There is also a pair of functions for printing filenames: |
| 186 | 191 | ||
| 187 | int seq_path(struct seq_file *m, struct path *path, char *esc); | 192 | int seq_path(struct seq_file *m, struct path *path, char *esc); |
| 193 | int seq_path_root(struct seq_file *m, struct path *path, | ||
| 194 | struct path *root, char *esc) | ||
| 188 | 195 | ||
| 189 | Here, path indicates the file of interest, and esc is a set of characters | 196 | Here, path indicates the file of interest, and esc is a set of characters |
| 190 | which should be escaped in the output. | 197 | which should be escaped in the output. A call to seq_path() will output |
| 198 | the path relative to the current process's filesystem root. If a different | ||
| 199 | root is desired, it can be used with seq_path_root(). Note that, if it | ||
| 200 | turns out that path cannot be reached from root, the value of root will be | ||
| 201 | changed in seq_file_root() to a root which *does* work. | ||
| 191 | 202 | ||
| 192 | 203 | ||
| 193 | Making it all work | 204 | Making it all work |
diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt index 1d247d59ad56..1821c077b435 100644 --- a/Documentation/kbuild/modules.txt +++ b/Documentation/kbuild/modules.txt | |||
| @@ -486,7 +486,7 @@ Module.symvers contains a list of all exported symbols from a kernel build. | |||
| 486 | Sometimes, an external module uses exported symbols from another | 486 | Sometimes, an external module uses exported symbols from another |
| 487 | external module. Kbuild needs to have full knowledge on all symbols | 487 | external module. Kbuild needs to have full knowledge on all symbols |
| 488 | to avoid spitting out warnings about undefined symbols. | 488 | to avoid spitting out warnings about undefined symbols. |
| 489 | Two solutions exist to let kbuild know all symbols of more than | 489 | Three solutions exist to let kbuild know all symbols of more than |
| 490 | one external module. | 490 | one external module. |
| 491 | The method with a top-level kbuild file is recommended but may be | 491 | The method with a top-level kbuild file is recommended but may be |
| 492 | impractical in certain situations. | 492 | impractical in certain situations. |
| @@ -523,6 +523,13 @@ Module.symvers contains a list of all exported symbols from a kernel build. | |||
| 523 | containing the sum of all symbols defined and not part of the | 523 | containing the sum of all symbols defined and not part of the |
| 524 | kernel. | 524 | kernel. |
| 525 | 525 | ||
| 526 | Use make variable KBUILD_EXTRA_SYMBOLS in the Makefile | ||
| 527 | If it is impractical to copy Module.symvers from another | ||
| 528 | module, you can assign a space separated list of files to | ||
| 529 | KBUILD_EXTRA_SYMBOLS in your Makfile. These files will be | ||
| 530 | loaded by modpost during the initialisation of its symbol | ||
| 531 | tables. | ||
| 532 | |||
| 526 | === 8. Tips & Tricks | 533 | === 8. Tips & Tricks |
| 527 | 534 | ||
| 528 | --- 8.1 Testing for CONFIG_FOO_BAR | 535 | --- 8.1 Testing for CONFIG_FOO_BAR |
diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt index 0bc95eab1512..8df6a7b0e66c 100644 --- a/Documentation/networking/phy.txt +++ b/Documentation/networking/phy.txt | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | 1 | ||
| 2 | ------- | 2 | ------- |
| 3 | PHY Abstraction Layer | 3 | PHY Abstraction Layer |
| 4 | (Updated 2006-11-30) | 4 | (Updated 2008-04-08) |
| 5 | 5 | ||
| 6 | Purpose | 6 | Purpose |
| 7 | 7 | ||
| @@ -291,3 +291,39 @@ Writing a PHY driver | |||
| 291 | Feel free to look at the Marvell, Cicada, and Davicom drivers in | 291 | Feel free to look at the Marvell, Cicada, and Davicom drivers in |
| 292 | drivers/net/phy/ for examples (the lxt and qsemi drivers have | 292 | drivers/net/phy/ for examples (the lxt and qsemi drivers have |
| 293 | not been tested as of this writing) | 293 | not been tested as of this writing) |
| 294 | |||
| 295 | Board Fixups | ||
| 296 | |||
| 297 | Sometimes the specific interaction between the platform and the PHY requires | ||
| 298 | special handling. For instance, to change where the PHY's clock input is, | ||
| 299 | or to add a delay to account for latency issues in the data path. In order | ||
| 300 | to support such contingencies, the PHY Layer allows platform code to register | ||
| 301 | fixups to be run when the PHY is brought up (or subsequently reset). | ||
| 302 | |||
| 303 | When the PHY Layer brings up a PHY it checks to see if there are any fixups | ||
| 304 | registered for it, matching based on UID (contained in the PHY device's phy_id | ||
| 305 | field) and the bus identifier (contained in phydev->dev.bus_id). Both must | ||
| 306 | match, however two constants, PHY_ANY_ID and PHY_ANY_UID, are provided as | ||
| 307 | wildcards for the bus ID and UID, respectively. | ||
| 308 | |||
| 309 | When a match is found, the PHY layer will invoke the run function associated | ||
| 310 | with the fixup. This function is passed a pointer to the phy_device of | ||
| 311 | interest. It should therefore only operate on that PHY. | ||
| 312 | |||
| 313 | The platform code can either register the fixup using phy_register_fixup(): | ||
| 314 | |||
| 315 | int phy_register_fixup(const char *phy_id, | ||
| 316 | u32 phy_uid, u32 phy_uid_mask, | ||
| 317 | int (*run)(struct phy_device *)); | ||
| 318 | |||
| 319 | Or using one of the two stubs, phy_register_fixup_for_uid() and | ||
| 320 | phy_register_fixup_for_id(): | ||
| 321 | |||
| 322 | int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask, | ||
| 323 | int (*run)(struct phy_device *)); | ||
| 324 | int phy_register_fixup_for_id(const char *phy_id, | ||
| 325 | int (*run)(struct phy_device *)); | ||
| 326 | |||
| 327 | The stubs set one of the two matching criteria, and set the other one to | ||
| 328 | match anything. | ||
| 329 | |||
| @@ -507,6 +507,10 @@ else | |||
| 507 | KBUILD_CFLAGS += -O2 | 507 | KBUILD_CFLAGS += -O2 |
| 508 | endif | 508 | endif |
| 509 | 509 | ||
| 510 | ifneq (CONFIG_FRAME_WARN,0) | ||
| 511 | KBUILD_CFLAGS += $(call cc-option,-Wframe-larger-than=${CONFIG_FRAME_WARN}) | ||
| 512 | endif | ||
| 513 | |||
| 510 | # Force gcc to behave correct even for buggy distributions | 514 | # Force gcc to behave correct even for buggy distributions |
| 511 | # Arch Makefiles may override this setting | 515 | # Arch Makefiles may override this setting |
| 512 | KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) | 516 | KBUILD_CFLAGS += $(call cc-option, -fno-stack-protector) |
| @@ -1396,7 +1400,7 @@ define xtags | |||
| 1396 | $(all-kconfigs) | xargs $1 -a \ | 1400 | $(all-kconfigs) | xargs $1 -a \ |
| 1397 | --langdef=kconfig \ | 1401 | --langdef=kconfig \ |
| 1398 | --language-force=kconfig \ | 1402 | --language-force=kconfig \ |
| 1399 | --regex-kconfig='/^[[:blank:]]*config[[:blank:]]+([[:alnum:]_]+)/\1/'; \ | 1403 | --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/\2/'; \ |
| 1400 | $(all-defconfigs) | xargs -r $1 -a \ | 1404 | $(all-defconfigs) | xargs -r $1 -a \ |
| 1401 | --langdef=dotconfig \ | 1405 | --langdef=dotconfig \ |
| 1402 | --language-force=dotconfig \ | 1406 | --language-force=dotconfig \ |
| @@ -1404,7 +1408,7 @@ define xtags | |||
| 1404 | elif $1 --version 2>&1 | grep -iq emacs; then \ | 1408 | elif $1 --version 2>&1 | grep -iq emacs; then \ |
| 1405 | $(all-sources) | xargs $1 -a; \ | 1409 | $(all-sources) | xargs $1 -a; \ |
| 1406 | $(all-kconfigs) | xargs $1 -a \ | 1410 | $(all-kconfigs) | xargs $1 -a \ |
| 1407 | --regex='/^[ \t]*config[ \t]+\([a-zA-Z0-9_]+\)/\1/'; \ | 1411 | --regex='/^[ \t]*(menu|)config[ \t]+\([a-zA-Z0-9_]+\)/\2/'; \ |
| 1408 | $(all-defconfigs) | xargs -r $1 -a \ | 1412 | $(all-defconfigs) | xargs -r $1 -a \ |
| 1409 | --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/'; \ | 1413 | --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/'; \ |
| 1410 | else \ | 1414 | else \ |
| @@ -1539,7 +1543,6 @@ quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN $(wildcard $(rm-files)) | |||
| 1539 | cmd_rmfiles = rm -f $(rm-files) | 1543 | cmd_rmfiles = rm -f $(rm-files) |
| 1540 | 1544 | ||
| 1541 | # Run depmod only if we have System.map and depmod is executable | 1545 | # Run depmod only if we have System.map and depmod is executable |
| 1542 | # and we build for the host arch | ||
| 1543 | quiet_cmd_depmod = DEPMOD $(KERNELRELEASE) | 1546 | quiet_cmd_depmod = DEPMOD $(KERNELRELEASE) |
| 1544 | cmd_depmod = \ | 1547 | cmd_depmod = \ |
| 1545 | if [ -r System.map -a -x $(DEPMOD) ]; then \ | 1548 | if [ -r System.map -a -x $(DEPMOD) ]; then \ |
diff --git a/arch/x86/boot/.gitignore b/arch/x86/boot/.gitignore index b1bdc4c6f9f2..172cf8a98bdd 100644 --- a/arch/x86/boot/.gitignore +++ b/arch/x86/boot/.gitignore | |||
| @@ -1,7 +1,8 @@ | |||
| 1 | bootsect | 1 | bootsect |
| 2 | bzImage | 2 | bzImage |
| 3 | cpustr.h | ||
| 4 | mkcpustr | ||
| 5 | offsets.h | ||
| 3 | setup | 6 | setup |
| 4 | setup.bin | 7 | setup.bin |
| 5 | setup.elf | 8 | setup.elf |
| 6 | cpustr.h | ||
| 7 | mkcpustr | ||
diff --git a/arch/x86/kernel/acpi/realmode/.gitignore b/arch/x86/kernel/acpi/realmode/.gitignore new file mode 100644 index 000000000000..58f1f48a58f8 --- /dev/null +++ b/arch/x86/kernel/acpi/realmode/.gitignore | |||
| @@ -0,0 +1,3 @@ | |||
| 1 | wakeup.bin | ||
| 2 | wakeup.elf | ||
| 3 | wakeup.lds | ||
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index df4099dc1c68..65c7857a90dd 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
| @@ -511,31 +511,30 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len) | |||
| 511 | unsigned long flags; | 511 | unsigned long flags; |
| 512 | char *vaddr; | 512 | char *vaddr; |
| 513 | int nr_pages = 2; | 513 | int nr_pages = 2; |
| 514 | struct page *pages[2]; | ||
| 515 | int i; | ||
| 514 | 516 | ||
| 515 | BUG_ON(len > sizeof(long)); | 517 | if (!core_kernel_text((unsigned long)addr)) { |
| 516 | BUG_ON((((long)addr + len - 1) & ~(sizeof(long) - 1)) | 518 | pages[0] = vmalloc_to_page(addr); |
| 517 | - ((long)addr & ~(sizeof(long) - 1))); | 519 | pages[1] = vmalloc_to_page(addr + PAGE_SIZE); |
| 518 | if (kernel_text_address((unsigned long)addr)) { | ||
| 519 | struct page *pages[2] = { virt_to_page(addr), | ||
| 520 | virt_to_page(addr + PAGE_SIZE) }; | ||
| 521 | if (!pages[1]) | ||
| 522 | nr_pages = 1; | ||
| 523 | vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL); | ||
| 524 | BUG_ON(!vaddr); | ||
| 525 | local_irq_save(flags); | ||
| 526 | memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len); | ||
| 527 | local_irq_restore(flags); | ||
| 528 | vunmap(vaddr); | ||
| 529 | } else { | 520 | } else { |
| 530 | /* | 521 | pages[0] = virt_to_page(addr); |
| 531 | * modules are in vmalloc'ed memory, always writable. | 522 | WARN_ON(!PageReserved(pages[0])); |
| 532 | */ | 523 | pages[1] = virt_to_page(addr + PAGE_SIZE); |
| 533 | local_irq_save(flags); | ||
| 534 | memcpy(addr, opcode, len); | ||
| 535 | local_irq_restore(flags); | ||
| 536 | } | 524 | } |
| 525 | BUG_ON(!pages[0]); | ||
| 526 | if (!pages[1]) | ||
| 527 | nr_pages = 1; | ||
| 528 | vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL); | ||
| 529 | BUG_ON(!vaddr); | ||
| 530 | local_irq_save(flags); | ||
| 531 | memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len); | ||
| 532 | local_irq_restore(flags); | ||
| 533 | vunmap(vaddr); | ||
| 537 | sync_core(); | 534 | sync_core(); |
| 538 | /* Could also do a CLFLUSH here to speed up CPU recovery; but | 535 | /* Could also do a CLFLUSH here to speed up CPU recovery; but |
| 539 | that causes hangs on some VIA CPUs. */ | 536 | that causes hangs on some VIA CPUs. */ |
| 537 | for (i = 0; i < len; i++) | ||
| 538 | BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]); | ||
| 540 | return addr; | 539 | return addr; |
| 541 | } | 540 | } |
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 1ff7906a9a4d..b798e7b92b17 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c | |||
| @@ -135,7 +135,7 @@ static __init void *spp_getpage(void) | |||
| 135 | return ptr; | 135 | return ptr; |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | static __init void | 138 | static void |
| 139 | set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot) | 139 | set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot) |
| 140 | { | 140 | { |
| 141 | pgd_t *pgd; | 141 | pgd_t *pgd; |
| @@ -173,7 +173,7 @@ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot) | |||
| 173 | new_pte = pfn_pte(phys >> PAGE_SHIFT, prot); | 173 | new_pte = pfn_pte(phys >> PAGE_SHIFT, prot); |
| 174 | 174 | ||
| 175 | pte = pte_offset_kernel(pmd, vaddr); | 175 | pte = pte_offset_kernel(pmd, vaddr); |
| 176 | if (!pte_none(*pte) && | 176 | if (!pte_none(*pte) && pte_val(new_pte) && |
| 177 | pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask)) | 177 | pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask)) |
| 178 | pte_ERROR(*pte); | 178 | pte_ERROR(*pte); |
| 179 | set_pte(pte, new_pte); | 179 | set_pte(pte, new_pte); |
| @@ -214,8 +214,7 @@ void __init cleanup_highmap(void) | |||
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | /* NOTE: this is meant to be run only at boot */ | 216 | /* NOTE: this is meant to be run only at boot */ |
| 217 | void __init | 217 | void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot) |
| 218 | __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot) | ||
| 219 | { | 218 | { |
| 220 | unsigned long address = __fix_to_virt(idx); | 219 | unsigned long address = __fix_to_virt(idx); |
| 221 | 220 | ||
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 6228fadacd38..9d19aec5820a 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c | |||
| @@ -2167,6 +2167,7 @@ static const struct file_operations dv1394_fops= | |||
| 2167 | /* | 2167 | /* |
| 2168 | * Export information about protocols/devices supported by this driver. | 2168 | * Export information about protocols/devices supported by this driver. |
| 2169 | */ | 2169 | */ |
| 2170 | #ifdef MODULE | ||
| 2170 | static struct ieee1394_device_id dv1394_id_table[] = { | 2171 | static struct ieee1394_device_id dv1394_id_table[] = { |
| 2171 | { | 2172 | { |
| 2172 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, | 2173 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, |
| @@ -2177,6 +2178,7 @@ static struct ieee1394_device_id dv1394_id_table[] = { | |||
| 2177 | }; | 2178 | }; |
| 2178 | 2179 | ||
| 2179 | MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table); | 2180 | MODULE_DEVICE_TABLE(ieee1394, dv1394_id_table); |
| 2181 | #endif /* MODULE */ | ||
| 2180 | 2182 | ||
| 2181 | static struct hpsb_protocol_driver dv1394_driver = { | 2183 | static struct hpsb_protocol_driver dv1394_driver = { |
| 2182 | .name = "dv1394", | 2184 | .name = "dv1394", |
diff --git a/drivers/ieee1394/iso.h b/drivers/ieee1394/iso.h index b94e55e6eaa5..b5de5f21ef78 100644 --- a/drivers/ieee1394/iso.h +++ b/drivers/ieee1394/iso.h | |||
| @@ -123,6 +123,8 @@ struct hpsb_iso { | |||
| 123 | 123 | ||
| 124 | /* how many times the buffer has overflowed or underflowed */ | 124 | /* how many times the buffer has overflowed or underflowed */ |
| 125 | atomic_t overflows; | 125 | atomic_t overflows; |
| 126 | /* how many cycles were skipped for a given context */ | ||
| 127 | atomic_t skips; | ||
| 126 | 128 | ||
| 127 | /* Current number of bytes lost in discarded packets */ | 129 | /* Current number of bytes lost in discarded packets */ |
| 128 | int bytes_discarded; | 130 | int bytes_discarded; |
diff --git a/drivers/ieee1394/ohci1394.c b/drivers/ieee1394/ohci1394.c index 0690469fcecf..e509e13cb7a7 100644 --- a/drivers/ieee1394/ohci1394.c +++ b/drivers/ieee1394/ohci1394.c | |||
| @@ -1723,6 +1723,8 @@ struct ohci_iso_xmit { | |||
| 1723 | struct dma_prog_region prog; | 1723 | struct dma_prog_region prog; |
| 1724 | struct ohci1394_iso_tasklet task; | 1724 | struct ohci1394_iso_tasklet task; |
| 1725 | int task_active; | 1725 | int task_active; |
| 1726 | int last_cycle; | ||
| 1727 | atomic_t skips; | ||
| 1726 | 1728 | ||
| 1727 | u32 ContextControlSet; | 1729 | u32 ContextControlSet; |
| 1728 | u32 ContextControlClear; | 1730 | u32 ContextControlClear; |
| @@ -1759,6 +1761,8 @@ static int ohci_iso_xmit_init(struct hpsb_iso *iso) | |||
| 1759 | iso->hostdata = xmit; | 1761 | iso->hostdata = xmit; |
| 1760 | xmit->ohci = iso->host->hostdata; | 1762 | xmit->ohci = iso->host->hostdata; |
| 1761 | xmit->task_active = 0; | 1763 | xmit->task_active = 0; |
| 1764 | xmit->last_cycle = -1; | ||
| 1765 | atomic_set(&iso->skips, 0); | ||
| 1762 | 1766 | ||
| 1763 | dma_prog_region_init(&xmit->prog); | 1767 | dma_prog_region_init(&xmit->prog); |
| 1764 | 1768 | ||
| @@ -1856,6 +1860,26 @@ static void ohci_iso_xmit_task(unsigned long data) | |||
| 1856 | /* parse cycle */ | 1860 | /* parse cycle */ |
| 1857 | cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF; | 1861 | cycle = le32_to_cpu(cmd->output_last.status) & 0x1FFF; |
| 1858 | 1862 | ||
| 1863 | if (xmit->last_cycle > -1) { | ||
| 1864 | int cycle_diff = cycle - xmit->last_cycle; | ||
| 1865 | int skip; | ||
| 1866 | |||
| 1867 | /* unwrap */ | ||
| 1868 | if (cycle_diff < 0) { | ||
| 1869 | cycle_diff += 8000; | ||
| 1870 | if (cycle_diff < 0) | ||
| 1871 | PRINT(KERN_ERR, "bogus cycle diff %d\n", | ||
| 1872 | cycle_diff); | ||
| 1873 | } | ||
| 1874 | |||
| 1875 | skip = cycle_diff - 1; | ||
| 1876 | if (skip > 0) { | ||
| 1877 | DBGMSG("skipped %d cycles without packet loss", skip); | ||
| 1878 | atomic_add(skip, &iso->skips); | ||
| 1879 | } | ||
| 1880 | } | ||
| 1881 | xmit->last_cycle = cycle; | ||
| 1882 | |||
| 1859 | /* tell the subsystem the packet has gone out */ | 1883 | /* tell the subsystem the packet has gone out */ |
| 1860 | hpsb_iso_packet_sent(iso, cycle, event != 0x11); | 1884 | hpsb_iso_packet_sent(iso, cycle, event != 0x11); |
| 1861 | 1885 | ||
| @@ -1943,6 +1967,16 @@ static int ohci_iso_xmit_queue(struct hpsb_iso *iso, struct hpsb_iso_packet_info | |||
| 1943 | prev->output_last.branchAddress = cpu_to_le32( | 1967 | prev->output_last.branchAddress = cpu_to_le32( |
| 1944 | dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3); | 1968 | dma_prog_region_offset_to_bus(&xmit->prog, sizeof(struct iso_xmit_cmd) * next_i) | 3); |
| 1945 | 1969 | ||
| 1970 | /* | ||
| 1971 | * Link the skip address to this descriptor itself. This causes a | ||
| 1972 | * context to skip a cycle whenever lost cycles or FIFO overruns occur, | ||
| 1973 | * without dropping the data at that point the application should then | ||
| 1974 | * decide whether this is an error condition or not. Some protocols | ||
| 1975 | * can deal with this by dropping some rate-matching padding packets. | ||
| 1976 | */ | ||
| 1977 | next->output_more_immediate.branchAddress = | ||
| 1978 | prev->output_last.branchAddress; | ||
| 1979 | |||
| 1946 | /* disable interrupt, unless required by the IRQ interval */ | 1980 | /* disable interrupt, unless required by the IRQ interval */ |
| 1947 | if (prev_i % iso->irq_interval) { | 1981 | if (prev_i % iso->irq_interval) { |
| 1948 | prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */ | 1982 | prev->output_last.control &= cpu_to_le32(~(3 << 20)); /* no interrupt */ |
diff --git a/drivers/ieee1394/raw1394.c b/drivers/ieee1394/raw1394.c index 04e96ba56e09..ec2a0adbedb2 100644 --- a/drivers/ieee1394/raw1394.c +++ b/drivers/ieee1394/raw1394.c | |||
| @@ -2356,13 +2356,16 @@ static void rawiso_activity_cb(struct hpsb_iso *iso) | |||
| 2356 | static void raw1394_iso_fill_status(struct hpsb_iso *iso, | 2356 | static void raw1394_iso_fill_status(struct hpsb_iso *iso, |
| 2357 | struct raw1394_iso_status *stat) | 2357 | struct raw1394_iso_status *stat) |
| 2358 | { | 2358 | { |
| 2359 | int overflows = atomic_read(&iso->overflows); | ||
| 2360 | int skips = atomic_read(&iso->skips); | ||
| 2361 | |||
| 2359 | stat->config.data_buf_size = iso->buf_size; | 2362 | stat->config.data_buf_size = iso->buf_size; |
| 2360 | stat->config.buf_packets = iso->buf_packets; | 2363 | stat->config.buf_packets = iso->buf_packets; |
| 2361 | stat->config.channel = iso->channel; | 2364 | stat->config.channel = iso->channel; |
| 2362 | stat->config.speed = iso->speed; | 2365 | stat->config.speed = iso->speed; |
| 2363 | stat->config.irq_interval = iso->irq_interval; | 2366 | stat->config.irq_interval = iso->irq_interval; |
| 2364 | stat->n_packets = hpsb_iso_n_ready(iso); | 2367 | stat->n_packets = hpsb_iso_n_ready(iso); |
| 2365 | stat->overflows = atomic_read(&iso->overflows); | 2368 | stat->overflows = ((skips & 0xFFFF) << 16) | ((overflows & 0xFFFF)); |
| 2366 | stat->xmit_cycle = iso->xmit_cycle; | 2369 | stat->xmit_cycle = iso->xmit_cycle; |
| 2367 | } | 2370 | } |
| 2368 | 2371 | ||
| @@ -2437,6 +2440,8 @@ static int raw1394_iso_get_status(struct file_info *fi, void __user * uaddr) | |||
| 2437 | 2440 | ||
| 2438 | /* reset overflow counter */ | 2441 | /* reset overflow counter */ |
| 2439 | atomic_set(&iso->overflows, 0); | 2442 | atomic_set(&iso->overflows, 0); |
| 2443 | /* reset skip counter */ | ||
| 2444 | atomic_set(&iso->skips, 0); | ||
| 2440 | 2445 | ||
| 2441 | return 0; | 2446 | return 0; |
| 2442 | } | 2447 | } |
| @@ -2935,6 +2940,7 @@ static int raw1394_release(struct inode *inode, struct file *file) | |||
| 2935 | /* | 2940 | /* |
| 2936 | * Export information about protocols/devices supported by this driver. | 2941 | * Export information about protocols/devices supported by this driver. |
| 2937 | */ | 2942 | */ |
| 2943 | #ifdef MODULE | ||
| 2938 | static struct ieee1394_device_id raw1394_id_table[] = { | 2944 | static struct ieee1394_device_id raw1394_id_table[] = { |
| 2939 | { | 2945 | { |
| 2940 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, | 2946 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, |
| @@ -2956,6 +2962,7 @@ static struct ieee1394_device_id raw1394_id_table[] = { | |||
| 2956 | }; | 2962 | }; |
| 2957 | 2963 | ||
| 2958 | MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table); | 2964 | MODULE_DEVICE_TABLE(ieee1394, raw1394_id_table); |
| 2965 | #endif /* MODULE */ | ||
| 2959 | 2966 | ||
| 2960 | static struct hpsb_protocol_driver raw1394_driver = { | 2967 | static struct hpsb_protocol_driver raw1394_driver = { |
| 2961 | .name = "raw1394", | 2968 | .name = "raw1394", |
diff --git a/drivers/ieee1394/video1394.c b/drivers/ieee1394/video1394.c index e03024eeeac1..e24772d336e1 100644 --- a/drivers/ieee1394/video1394.c +++ b/drivers/ieee1394/video1394.c | |||
| @@ -1293,6 +1293,7 @@ static const struct file_operations video1394_fops= | |||
| 1293 | /* | 1293 | /* |
| 1294 | * Export information about protocols/devices supported by this driver. | 1294 | * Export information about protocols/devices supported by this driver. |
| 1295 | */ | 1295 | */ |
| 1296 | #ifdef MODULE | ||
| 1296 | static struct ieee1394_device_id video1394_id_table[] = { | 1297 | static struct ieee1394_device_id video1394_id_table[] = { |
| 1297 | { | 1298 | { |
| 1298 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, | 1299 | .match_flags = IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION, |
| @@ -1313,6 +1314,7 @@ static struct ieee1394_device_id video1394_id_table[] = { | |||
| 1313 | }; | 1314 | }; |
| 1314 | 1315 | ||
| 1315 | MODULE_DEVICE_TABLE(ieee1394, video1394_id_table); | 1316 | MODULE_DEVICE_TABLE(ieee1394, video1394_id_table); |
| 1317 | #endif /* MODULE */ | ||
| 1316 | 1318 | ||
| 1317 | static struct hpsb_protocol_driver video1394_driver = { | 1319 | static struct hpsb_protocol_driver video1394_driver = { |
| 1318 | .name = VIDEO1394_DRIVER_NAME, | 1320 | .name = VIDEO1394_DRIVER_NAME, |
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index e8503341e3b1..eed06d068fd1 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig | |||
| @@ -158,6 +158,12 @@ config MTD_OF_PARTS | |||
| 158 | the partition map from the children of the flash node, | 158 | the partition map from the children of the flash node, |
| 159 | as described in Documentation/powerpc/booting-without-of.txt. | 159 | as described in Documentation/powerpc/booting-without-of.txt. |
| 160 | 160 | ||
| 161 | config MTD_AR7_PARTS | ||
| 162 | tristate "TI AR7 partitioning support" | ||
| 163 | depends on MTD_PARTITIONS | ||
| 164 | ---help--- | ||
| 165 | TI AR7 partitioning support | ||
| 166 | |||
| 161 | comment "User Modules And Translation Layers" | 167 | comment "User Modules And Translation Layers" |
| 162 | 168 | ||
| 163 | config MTD_CHAR | 169 | config MTD_CHAR |
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index 538e33d11d46..4b77335715f0 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile | |||
| @@ -11,6 +11,7 @@ obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o | |||
| 11 | obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o | 11 | obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o |
| 12 | obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o | 12 | obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o |
| 13 | obj-$(CONFIG_MTD_AFS_PARTS) += afs.o | 13 | obj-$(CONFIG_MTD_AFS_PARTS) += afs.o |
| 14 | obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o | ||
| 14 | obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o | 15 | obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o |
| 15 | 16 | ||
| 16 | # 'Users' - code which presents functionality to userspace. | 17 | # 'Users' - code which presents functionality to userspace. |
diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c new file mode 100644 index 000000000000..ecf170b55c32 --- /dev/null +++ b/drivers/mtd/ar7part.c | |||
| @@ -0,0 +1,151 @@ | |||
| 1 | /* | ||
| 2 | * Copyright © 2007 Eugene Konev <ejka@openwrt.org> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License as published by | ||
| 6 | * the Free Software Foundation; either version 2 of the License, or | ||
| 7 | * (at your option) any later version. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 17 | * | ||
| 18 | * TI AR7 flash partition table. | ||
| 19 | * Based on ar7 map by Felix Fietkau <nbd@openwrt.org> | ||
| 20 | * | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/slab.h> | ||
| 25 | |||
| 26 | #include <linux/mtd/mtd.h> | ||
| 27 | #include <linux/mtd/partitions.h> | ||
| 28 | #include <linux/bootmem.h> | ||
| 29 | #include <linux/magic.h> | ||
| 30 | |||
| 31 | #define AR7_PARTS 4 | ||
| 32 | #define ROOT_OFFSET 0xe0000 | ||
| 33 | |||
| 34 | #define LOADER_MAGIC1 le32_to_cpu(0xfeedfa42) | ||
| 35 | #define LOADER_MAGIC2 le32_to_cpu(0xfeed1281) | ||
| 36 | |||
| 37 | #ifndef SQUASHFS_MAGIC | ||
| 38 | #define SQUASHFS_MAGIC 0x73717368 | ||
| 39 | #endif | ||
| 40 | |||
| 41 | struct ar7_bin_rec { | ||
| 42 | unsigned int checksum; | ||
| 43 | unsigned int length; | ||
| 44 | unsigned int address; | ||
| 45 | }; | ||
| 46 | |||
| 47 | static struct mtd_partition ar7_parts[AR7_PARTS]; | ||
| 48 | |||
| 49 | static int create_mtd_partitions(struct mtd_info *master, | ||
| 50 | struct mtd_partition **pparts, | ||
| 51 | unsigned long origin) | ||
| 52 | { | ||
| 53 | struct ar7_bin_rec header; | ||
| 54 | unsigned int offset; | ||
| 55 | size_t len; | ||
| 56 | unsigned int pre_size = master->erasesize, post_size = 0; | ||
| 57 | unsigned int root_offset = ROOT_OFFSET; | ||
| 58 | |||
| 59 | int retries = 10; | ||
| 60 | |||
| 61 | ar7_parts[0].name = "loader"; | ||
| 62 | ar7_parts[0].offset = 0; | ||
| 63 | ar7_parts[0].size = master->erasesize; | ||
| 64 | ar7_parts[0].mask_flags = MTD_WRITEABLE; | ||
| 65 | |||
| 66 | ar7_parts[1].name = "config"; | ||
| 67 | ar7_parts[1].offset = 0; | ||
| 68 | ar7_parts[1].size = master->erasesize; | ||
| 69 | ar7_parts[1].mask_flags = 0; | ||
| 70 | |||
| 71 | do { /* Try 10 blocks starting from master->erasesize */ | ||
| 72 | offset = pre_size; | ||
| 73 | master->read(master, offset, | ||
| 74 | sizeof(header), &len, (uint8_t *)&header); | ||
| 75 | if (!strncmp((char *)&header, "TIENV0.8", 8)) | ||
| 76 | ar7_parts[1].offset = pre_size; | ||
| 77 | if (header.checksum == LOADER_MAGIC1) | ||
| 78 | break; | ||
| 79 | if (header.checksum == LOADER_MAGIC2) | ||
| 80 | break; | ||
| 81 | pre_size += master->erasesize; | ||
| 82 | } while (retries--); | ||
| 83 | |||
| 84 | pre_size = offset; | ||
| 85 | |||
| 86 | if (!ar7_parts[1].offset) { | ||
| 87 | ar7_parts[1].offset = master->size - master->erasesize; | ||
| 88 | post_size = master->erasesize; | ||
| 89 | } | ||
| 90 | |||
| 91 | switch (header.checksum) { | ||
| 92 | case LOADER_MAGIC1: | ||
| 93 | while (header.length) { | ||
| 94 | offset += sizeof(header) + header.length; | ||
| 95 | master->read(master, offset, sizeof(header), | ||
| 96 | &len, (uint8_t *)&header); | ||
| 97 | } | ||
| 98 | root_offset = offset + sizeof(header) + 4; | ||
| 99 | break; | ||
| 100 | case LOADER_MAGIC2: | ||
| 101 | while (header.length) { | ||
| 102 | offset += sizeof(header) + header.length; | ||
| 103 | master->read(master, offset, sizeof(header), | ||
| 104 | &len, (uint8_t *)&header); | ||
| 105 | } | ||
| 106 | root_offset = offset + sizeof(header) + 4 + 0xff; | ||
| 107 | root_offset &= ~(uint32_t)0xff; | ||
| 108 | break; | ||
| 109 | default: | ||
| 110 | printk(KERN_WARNING "Unknown magic: %08x\n", header.checksum); | ||
| 111 | break; | ||
| 112 | } | ||
| 113 | |||
| 114 | master->read(master, root_offset, | ||
| 115 | sizeof(header), &len, (u8 *)&header); | ||
| 116 | if (header.checksum != SQUASHFS_MAGIC) { | ||
| 117 | root_offset += master->erasesize - 1; | ||
| 118 | root_offset &= ~(master->erasesize - 1); | ||
| 119 | } | ||
| 120 | |||
| 121 | ar7_parts[2].name = "linux"; | ||
| 122 | ar7_parts[2].offset = pre_size; | ||
| 123 | ar7_parts[2].size = master->size - pre_size - post_size; | ||
| 124 | ar7_parts[2].mask_flags = 0; | ||
| 125 | |||
| 126 | ar7_parts[3].name = "rootfs"; | ||
| 127 | ar7_parts[3].offset = root_offset; | ||
| 128 | ar7_parts[3].size = master->size - root_offset - post_size; | ||
| 129 | ar7_parts[3].mask_flags = 0; | ||
| 130 | |||
| 131 | *pparts = ar7_parts; | ||
| 132 | return AR7_PARTS; | ||
| 133 | } | ||
| 134 | |||
| 135 | static struct mtd_part_parser ar7_parser = { | ||
| 136 | .owner = THIS_MODULE, | ||
| 137 | .parse_fn = create_mtd_partitions, | ||
| 138 | .name = "ar7part", | ||
| 139 | }; | ||
| 140 | |||
| 141 | static int __init ar7_parser_init(void) | ||
| 142 | { | ||
| 143 | return register_mtd_parser(&ar7_parser); | ||
| 144 | } | ||
| 145 | |||
| 146 | module_init(ar7_parser_init); | ||
| 147 | |||
| 148 | MODULE_LICENSE("GPL"); | ||
| 149 | MODULE_AUTHOR( "Felix Fietkau <nbd@openwrt.org>, " | ||
| 150 | "Eugene Konev <ejka@openwrt.org>"); | ||
| 151 | MODULE_DESCRIPTION("MTD partitioning for TI AR7"); | ||
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 0080452531d6..e812df607a5c 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c | |||
| @@ -384,7 +384,7 @@ read_pri_intelext(struct map_info *map, __u16 adr) | |||
| 384 | if (extp_size > 4096) { | 384 | if (extp_size > 4096) { |
| 385 | printk(KERN_ERR | 385 | printk(KERN_ERR |
| 386 | "%s: cfi_pri_intelext is too fat\n", | 386 | "%s: cfi_pri_intelext is too fat\n", |
| 387 | __FUNCTION__); | 387 | __func__); |
| 388 | return NULL; | 388 | return NULL; |
| 389 | } | 389 | } |
| 390 | goto again; | 390 | goto again; |
| @@ -619,6 +619,9 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, | |||
| 619 | sizeof(struct cfi_intelext_blockinfo); | 619 | sizeof(struct cfi_intelext_blockinfo); |
| 620 | } | 620 | } |
| 621 | 621 | ||
| 622 | if (!numparts) | ||
| 623 | numparts = 1; | ||
| 624 | |||
| 622 | /* Programming Region info */ | 625 | /* Programming Region info */ |
| 623 | if (extp->MinorVersion >= '4') { | 626 | if (extp->MinorVersion >= '4') { |
| 624 | struct cfi_intelext_programming_regioninfo *prinfo; | 627 | struct cfi_intelext_programming_regioninfo *prinfo; |
| @@ -641,7 +644,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, | |||
| 641 | if ((1 << partshift) < mtd->erasesize) { | 644 | if ((1 << partshift) < mtd->erasesize) { |
| 642 | printk( KERN_ERR | 645 | printk( KERN_ERR |
| 643 | "%s: bad number of hw partitions (%d)\n", | 646 | "%s: bad number of hw partitions (%d)\n", |
| 644 | __FUNCTION__, numparts); | 647 | __func__, numparts); |
| 645 | return -EINVAL; | 648 | return -EINVAL; |
| 646 | } | 649 | } |
| 647 | 650 | ||
| @@ -1071,10 +1074,10 @@ static int __xipram xip_wait_for_operation( | |||
| 1071 | chip->state = newstate; | 1074 | chip->state = newstate; |
| 1072 | map_write(map, CMD(0xff), adr); | 1075 | map_write(map, CMD(0xff), adr); |
| 1073 | (void) map_read(map, adr); | 1076 | (void) map_read(map, adr); |
| 1074 | asm volatile (".rep 8; nop; .endr"); | 1077 | xip_iprefetch(); |
| 1075 | local_irq_enable(); | 1078 | local_irq_enable(); |
| 1076 | spin_unlock(chip->mutex); | 1079 | spin_unlock(chip->mutex); |
| 1077 | asm volatile (".rep 8; nop; .endr"); | 1080 | xip_iprefetch(); |
| 1078 | cond_resched(); | 1081 | cond_resched(); |
| 1079 | 1082 | ||
| 1080 | /* | 1083 | /* |
| @@ -2013,7 +2016,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len) | |||
| 2013 | 2016 | ||
| 2014 | #ifdef DEBUG_LOCK_BITS | 2017 | #ifdef DEBUG_LOCK_BITS |
| 2015 | printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", | 2018 | printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", |
| 2016 | __FUNCTION__, ofs, len); | 2019 | __func__, ofs, len); |
| 2017 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, | 2020 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, |
| 2018 | ofs, len, NULL); | 2021 | ofs, len, NULL); |
| 2019 | #endif | 2022 | #endif |
| @@ -2023,7 +2026,7 @@ static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, size_t len) | |||
| 2023 | 2026 | ||
| 2024 | #ifdef DEBUG_LOCK_BITS | 2027 | #ifdef DEBUG_LOCK_BITS |
| 2025 | printk(KERN_DEBUG "%s: lock status after, ret=%d\n", | 2028 | printk(KERN_DEBUG "%s: lock status after, ret=%d\n", |
| 2026 | __FUNCTION__, ret); | 2029 | __func__, ret); |
| 2027 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, | 2030 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, |
| 2028 | ofs, len, NULL); | 2031 | ofs, len, NULL); |
| 2029 | #endif | 2032 | #endif |
| @@ -2037,7 +2040,7 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) | |||
| 2037 | 2040 | ||
| 2038 | #ifdef DEBUG_LOCK_BITS | 2041 | #ifdef DEBUG_LOCK_BITS |
| 2039 | printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", | 2042 | printk(KERN_DEBUG "%s: lock status before, ofs=0x%08llx, len=0x%08X\n", |
| 2040 | __FUNCTION__, ofs, len); | 2043 | __func__, ofs, len); |
| 2041 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, | 2044 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, |
| 2042 | ofs, len, NULL); | 2045 | ofs, len, NULL); |
| 2043 | #endif | 2046 | #endif |
| @@ -2047,7 +2050,7 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) | |||
| 2047 | 2050 | ||
| 2048 | #ifdef DEBUG_LOCK_BITS | 2051 | #ifdef DEBUG_LOCK_BITS |
| 2049 | printk(KERN_DEBUG "%s: lock status after, ret=%d\n", | 2052 | printk(KERN_DEBUG "%s: lock status after, ret=%d\n", |
| 2050 | __FUNCTION__, ret); | 2053 | __func__, ret); |
| 2051 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, | 2054 | cfi_varsize_frob(mtd, do_printlockstatus_oneblock, |
| 2052 | ofs, len, NULL); | 2055 | ofs, len, NULL); |
| 2053 | #endif | 2056 | #endif |
diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 458d477614d6..f7fcc6389533 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | |||
| @@ -220,6 +220,28 @@ static void fixup_use_atmel_lock(struct mtd_info *mtd, void *param) | |||
| 220 | mtd->flags |= MTD_POWERUP_LOCK; | 220 | mtd->flags |= MTD_POWERUP_LOCK; |
| 221 | } | 221 | } |
| 222 | 222 | ||
| 223 | static void fixup_s29gl064n_sectors(struct mtd_info *mtd, void *param) | ||
| 224 | { | ||
| 225 | struct map_info *map = mtd->priv; | ||
| 226 | struct cfi_private *cfi = map->fldrv_priv; | ||
| 227 | |||
| 228 | if ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0x003f) { | ||
| 229 | cfi->cfiq->EraseRegionInfo[0] |= 0x0040; | ||
| 230 | pr_warning("%s: Bad S29GL064N CFI data, adjust from 64 to 128 sectors\n", mtd->name); | ||
| 231 | } | ||
| 232 | } | ||
| 233 | |||
| 234 | static void fixup_s29gl032n_sectors(struct mtd_info *mtd, void *param) | ||
| 235 | { | ||
| 236 | struct map_info *map = mtd->priv; | ||
| 237 | struct cfi_private *cfi = map->fldrv_priv; | ||
| 238 | |||
| 239 | if ((cfi->cfiq->EraseRegionInfo[1] & 0xffff) == 0x007e) { | ||
| 240 | cfi->cfiq->EraseRegionInfo[1] &= ~0x0040; | ||
| 241 | pr_warning("%s: Bad S29GL032N CFI data, adjust from 127 to 63 sectors\n", mtd->name); | ||
| 242 | } | ||
| 243 | } | ||
| 244 | |||
| 223 | static struct cfi_fixup cfi_fixup_table[] = { | 245 | static struct cfi_fixup cfi_fixup_table[] = { |
| 224 | { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, | 246 | { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, |
| 225 | #ifdef AMD_BOOTLOC_BUG | 247 | #ifdef AMD_BOOTLOC_BUG |
| @@ -231,6 +253,10 @@ static struct cfi_fixup cfi_fixup_table[] = { | |||
| 231 | { CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, }, | 253 | { CFI_MFR_AMD, 0x0056, fixup_use_secsi, NULL, }, |
| 232 | { CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, }, | 254 | { CFI_MFR_AMD, 0x005C, fixup_use_secsi, NULL, }, |
| 233 | { CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, }, | 255 | { CFI_MFR_AMD, 0x005F, fixup_use_secsi, NULL, }, |
| 256 | { CFI_MFR_AMD, 0x0c01, fixup_s29gl064n_sectors, NULL, }, | ||
| 257 | { CFI_MFR_AMD, 0x1301, fixup_s29gl064n_sectors, NULL, }, | ||
| 258 | { CFI_MFR_AMD, 0x1a00, fixup_s29gl032n_sectors, NULL, }, | ||
| 259 | { CFI_MFR_AMD, 0x1a01, fixup_s29gl032n_sectors, NULL, }, | ||
| 234 | #if !FORCE_WORD_WRITE | 260 | #if !FORCE_WORD_WRITE |
| 235 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, | 261 | { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL, }, |
| 236 | #endif | 262 | #endif |
| @@ -723,10 +749,10 @@ static void __xipram xip_udelay(struct map_info *map, struct flchip *chip, | |||
| 723 | chip->erase_suspended = 1; | 749 | chip->erase_suspended = 1; |
| 724 | map_write(map, CMD(0xf0), adr); | 750 | map_write(map, CMD(0xf0), adr); |
| 725 | (void) map_read(map, adr); | 751 | (void) map_read(map, adr); |
| 726 | asm volatile (".rep 8; nop; .endr"); | 752 | xip_iprefetch(); |
| 727 | local_irq_enable(); | 753 | local_irq_enable(); |
| 728 | spin_unlock(chip->mutex); | 754 | spin_unlock(chip->mutex); |
| 729 | asm volatile (".rep 8; nop; .endr"); | 755 | xip_iprefetch(); |
| 730 | cond_resched(); | 756 | cond_resched(); |
| 731 | 757 | ||
| 732 | /* | 758 | /* |
diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index 492e2ab27420..1b720cc571f3 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c | |||
| @@ -445,7 +445,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, | |||
| 445 | retry: | 445 | retry: |
| 446 | 446 | ||
| 447 | #ifdef DEBUG_CFI_FEATURES | 447 | #ifdef DEBUG_CFI_FEATURES |
| 448 | printk("%s: chip->state[%d]\n", __FUNCTION__, chip->state); | 448 | printk("%s: chip->state[%d]\n", __func__, chip->state); |
| 449 | #endif | 449 | #endif |
| 450 | spin_lock_bh(chip->mutex); | 450 | spin_lock_bh(chip->mutex); |
| 451 | 451 | ||
| @@ -463,7 +463,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, | |||
| 463 | map_write(map, CMD(0x70), cmd_adr); | 463 | map_write(map, CMD(0x70), cmd_adr); |
| 464 | chip->state = FL_STATUS; | 464 | chip->state = FL_STATUS; |
| 465 | #ifdef DEBUG_CFI_FEATURES | 465 | #ifdef DEBUG_CFI_FEATURES |
| 466 | printk("%s: 1 status[%x]\n", __FUNCTION__, map_read(map, cmd_adr)); | 466 | printk("%s: 1 status[%x]\n", __func__, map_read(map, cmd_adr)); |
| 467 | #endif | 467 | #endif |
| 468 | 468 | ||
| 469 | case FL_STATUS: | 469 | case FL_STATUS: |
| @@ -591,7 +591,7 @@ static inline int do_write_buffer(struct map_info *map, struct flchip *chip, | |||
| 591 | /* check for errors: 'lock bit', 'VPP', 'dead cell'/'unerased cell' or 'incorrect cmd' -- saw */ | 591 | /* check for errors: 'lock bit', 'VPP', 'dead cell'/'unerased cell' or 'incorrect cmd' -- saw */ |
| 592 | if (map_word_bitsset(map, status, CMD(0x3a))) { | 592 | if (map_word_bitsset(map, status, CMD(0x3a))) { |
| 593 | #ifdef DEBUG_CFI_FEATURES | 593 | #ifdef DEBUG_CFI_FEATURES |
| 594 | printk("%s: 2 status[%lx]\n", __FUNCTION__, status.x[0]); | 594 | printk("%s: 2 status[%lx]\n", __func__, status.x[0]); |
| 595 | #endif | 595 | #endif |
| 596 | /* clear status */ | 596 | /* clear status */ |
| 597 | map_write(map, CMD(0x50), cmd_adr); | 597 | map_write(map, CMD(0x50), cmd_adr); |
| @@ -625,9 +625,9 @@ static int cfi_staa_write_buffers (struct mtd_info *mtd, loff_t to, | |||
| 625 | ofs = to - (chipnum << cfi->chipshift); | 625 | ofs = to - (chipnum << cfi->chipshift); |
| 626 | 626 | ||
| 627 | #ifdef DEBUG_CFI_FEATURES | 627 | #ifdef DEBUG_CFI_FEATURES |
| 628 | printk("%s: map_bankwidth(map)[%x]\n", __FUNCTION__, map_bankwidth(map)); | 628 | printk("%s: map_bankwidth(map)[%x]\n", __func__, map_bankwidth(map)); |
| 629 | printk("%s: chipnum[%x] wbufsize[%x]\n", __FUNCTION__, chipnum, wbufsize); | 629 | printk("%s: chipnum[%x] wbufsize[%x]\n", __func__, chipnum, wbufsize); |
| 630 | printk("%s: ofs[%x] len[%x]\n", __FUNCTION__, ofs, len); | 630 | printk("%s: ofs[%x] len[%x]\n", __func__, ofs, len); |
| 631 | #endif | 631 | #endif |
| 632 | 632 | ||
| 633 | /* Write buffer is worth it only if more than one word to write... */ | 633 | /* Write buffer is worth it only if more than one word to write... */ |
| @@ -893,7 +893,8 @@ retry: | |||
| 893 | return ret; | 893 | return ret; |
| 894 | } | 894 | } |
| 895 | 895 | ||
| 896 | int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) | 896 | static int cfi_staa_erase_varsize(struct mtd_info *mtd, |
| 897 | struct erase_info *instr) | ||
| 897 | { struct map_info *map = mtd->priv; | 898 | { struct map_info *map = mtd->priv; |
| 898 | struct cfi_private *cfi = map->fldrv_priv; | 899 | struct cfi_private *cfi = map->fldrv_priv; |
| 899 | unsigned long adr, len; | 900 | unsigned long adr, len; |
diff --git a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c index f651b6ef1c5d..a4463a91ce31 100644 --- a/drivers/mtd/chips/cfi_probe.c +++ b/drivers/mtd/chips/cfi_probe.c | |||
| @@ -39,7 +39,7 @@ struct mtd_info *cfi_probe(struct map_info *map); | |||
| 39 | #define xip_allowed(base, map) \ | 39 | #define xip_allowed(base, map) \ |
| 40 | do { \ | 40 | do { \ |
| 41 | (void) map_read(map, base); \ | 41 | (void) map_read(map, base); \ |
| 42 | asm volatile (".rep 8; nop; .endr"); \ | 42 | xip_iprefetch(); \ |
| 43 | local_irq_enable(); \ | 43 | local_irq_enable(); \ |
| 44 | } while (0) | 44 | } while (0) |
| 45 | 45 | ||
| @@ -232,6 +232,11 @@ static int __xipram cfi_chip_setup(struct map_info *map, | |||
| 232 | cfi->mfr = cfi_read_query16(map, base); | 232 | cfi->mfr = cfi_read_query16(map, base); |
| 233 | cfi->id = cfi_read_query16(map, base + ofs_factor); | 233 | cfi->id = cfi_read_query16(map, base + ofs_factor); |
| 234 | 234 | ||
| 235 | /* Get AMD/Spansion extended JEDEC ID */ | ||
| 236 | if (cfi->mfr == CFI_MFR_AMD && (cfi->id & 0xff) == 0x7e) | ||
| 237 | cfi->id = cfi_read_query(map, base + 0xe * ofs_factor) << 8 | | ||
| 238 | cfi_read_query(map, base + 0xf * ofs_factor); | ||
| 239 | |||
| 235 | /* Put it back into Read Mode */ | 240 | /* Put it back into Read Mode */ |
| 236 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); | 241 | cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); |
| 237 | /* ... even if it's an Intel chip */ | 242 | /* ... even if it's an Intel chip */ |
diff --git a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c index 2e51496c248e..72e0022a47bf 100644 --- a/drivers/mtd/chips/cfi_util.c +++ b/drivers/mtd/chips/cfi_util.c | |||
| @@ -65,7 +65,7 @@ __xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* n | |||
| 65 | 65 | ||
| 66 | #ifdef CONFIG_MTD_XIP | 66 | #ifdef CONFIG_MTD_XIP |
| 67 | (void) map_read(map, base); | 67 | (void) map_read(map, base); |
| 68 | asm volatile (".rep 8; nop; .endr"); | 68 | xip_iprefetch(); |
| 69 | local_irq_enable(); | 69 | local_irq_enable(); |
| 70 | #endif | 70 | #endif |
| 71 | 71 | ||
diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index 4be51a86a85c..aa07575eb288 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c | |||
| @@ -132,6 +132,8 @@ | |||
| 132 | #define M29F800AB 0x0058 | 132 | #define M29F800AB 0x0058 |
| 133 | #define M29W800DT 0x00D7 | 133 | #define M29W800DT 0x00D7 |
| 134 | #define M29W800DB 0x005B | 134 | #define M29W800DB 0x005B |
| 135 | #define M29W400DT 0x00EE | ||
| 136 | #define M29W400DB 0x00EF | ||
| 135 | #define M29W160DT 0x22C4 | 137 | #define M29W160DT 0x22C4 |
| 136 | #define M29W160DB 0x2249 | 138 | #define M29W160DB 0x2249 |
| 137 | #define M29W040B 0x00E3 | 139 | #define M29W040B 0x00E3 |
| @@ -160,6 +162,7 @@ | |||
| 160 | #define SST49LF030A 0x001C | 162 | #define SST49LF030A 0x001C |
| 161 | #define SST49LF040A 0x0051 | 163 | #define SST49LF040A 0x0051 |
| 162 | #define SST49LF080A 0x005B | 164 | #define SST49LF080A 0x005B |
| 165 | #define SST36VF3203 0x7354 | ||
| 163 | 166 | ||
| 164 | /* Toshiba */ | 167 | /* Toshiba */ |
| 165 | #define TC58FVT160 0x00C2 | 168 | #define TC58FVT160 0x00C2 |
| @@ -1113,7 +1116,7 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1113 | .regions = { | 1116 | .regions = { |
| 1114 | ERASEINFO(0x10000,8), | 1117 | ERASEINFO(0x10000,8), |
| 1115 | } | 1118 | } |
| 1116 | }, { | 1119 | }, { |
| 1117 | .mfr_id = MANUFACTURER_MACRONIX, | 1120 | .mfr_id = MANUFACTURER_MACRONIX, |
| 1118 | .dev_id = MX29F016, | 1121 | .dev_id = MX29F016, |
| 1119 | .name = "Macronix MX29F016", | 1122 | .name = "Macronix MX29F016", |
| @@ -1125,7 +1128,7 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1125 | .regions = { | 1128 | .regions = { |
| 1126 | ERASEINFO(0x10000,32), | 1129 | ERASEINFO(0x10000,32), |
| 1127 | } | 1130 | } |
| 1128 | }, { | 1131 | }, { |
| 1129 | .mfr_id = MANUFACTURER_MACRONIX, | 1132 | .mfr_id = MANUFACTURER_MACRONIX, |
| 1130 | .dev_id = MX29F004T, | 1133 | .dev_id = MX29F004T, |
| 1131 | .name = "Macronix MX29F004T", | 1134 | .name = "Macronix MX29F004T", |
| @@ -1140,7 +1143,7 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1140 | ERASEINFO(0x02000,2), | 1143 | ERASEINFO(0x02000,2), |
| 1141 | ERASEINFO(0x04000,1), | 1144 | ERASEINFO(0x04000,1), |
| 1142 | } | 1145 | } |
| 1143 | }, { | 1146 | }, { |
| 1144 | .mfr_id = MANUFACTURER_MACRONIX, | 1147 | .mfr_id = MANUFACTURER_MACRONIX, |
| 1145 | .dev_id = MX29F004B, | 1148 | .dev_id = MX29F004B, |
| 1146 | .name = "Macronix MX29F004B", | 1149 | .name = "Macronix MX29F004B", |
| @@ -1218,7 +1221,7 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1218 | .regions = { | 1221 | .regions = { |
| 1219 | ERASEINFO(0x40000,16), | 1222 | ERASEINFO(0x40000,16), |
| 1220 | } | 1223 | } |
| 1221 | }, { | 1224 | }, { |
| 1222 | .mfr_id = MANUFACTURER_SST, | 1225 | .mfr_id = MANUFACTURER_SST, |
| 1223 | .dev_id = SST39LF512, | 1226 | .dev_id = SST39LF512, |
| 1224 | .name = "SST 39LF512", | 1227 | .name = "SST 39LF512", |
| @@ -1230,7 +1233,7 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1230 | .regions = { | 1233 | .regions = { |
| 1231 | ERASEINFO(0x01000,16), | 1234 | ERASEINFO(0x01000,16), |
| 1232 | } | 1235 | } |
| 1233 | }, { | 1236 | }, { |
| 1234 | .mfr_id = MANUFACTURER_SST, | 1237 | .mfr_id = MANUFACTURER_SST, |
| 1235 | .dev_id = SST39LF010, | 1238 | .dev_id = SST39LF010, |
| 1236 | .name = "SST 39LF010", | 1239 | .name = "SST 39LF010", |
| @@ -1242,7 +1245,7 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1242 | .regions = { | 1245 | .regions = { |
| 1243 | ERASEINFO(0x01000,32), | 1246 | ERASEINFO(0x01000,32), |
| 1244 | } | 1247 | } |
| 1245 | }, { | 1248 | }, { |
| 1246 | .mfr_id = MANUFACTURER_SST, | 1249 | .mfr_id = MANUFACTURER_SST, |
| 1247 | .dev_id = SST29EE020, | 1250 | .dev_id = SST29EE020, |
| 1248 | .name = "SST 29EE020", | 1251 | .name = "SST 29EE020", |
| @@ -1276,7 +1279,7 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1276 | .regions = { | 1279 | .regions = { |
| 1277 | ERASEINFO(0x01000,64), | 1280 | ERASEINFO(0x01000,64), |
| 1278 | } | 1281 | } |
| 1279 | }, { | 1282 | }, { |
| 1280 | .mfr_id = MANUFACTURER_SST, | 1283 | .mfr_id = MANUFACTURER_SST, |
| 1281 | .dev_id = SST39LF040, | 1284 | .dev_id = SST39LF040, |
| 1282 | .name = "SST 39LF040", | 1285 | .name = "SST 39LF040", |
| @@ -1288,7 +1291,7 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1288 | .regions = { | 1291 | .regions = { |
| 1289 | ERASEINFO(0x01000,128), | 1292 | ERASEINFO(0x01000,128), |
| 1290 | } | 1293 | } |
| 1291 | }, { | 1294 | }, { |
| 1292 | .mfr_id = MANUFACTURER_SST, | 1295 | .mfr_id = MANUFACTURER_SST, |
| 1293 | .dev_id = SST39SF010A, | 1296 | .dev_id = SST39SF010A, |
| 1294 | .name = "SST 39SF010A", | 1297 | .name = "SST 39SF010A", |
| @@ -1300,7 +1303,7 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1300 | .regions = { | 1303 | .regions = { |
| 1301 | ERASEINFO(0x01000,32), | 1304 | ERASEINFO(0x01000,32), |
| 1302 | } | 1305 | } |
| 1303 | }, { | 1306 | }, { |
| 1304 | .mfr_id = MANUFACTURER_SST, | 1307 | .mfr_id = MANUFACTURER_SST, |
| 1305 | .dev_id = SST39SF020A, | 1308 | .dev_id = SST39SF020A, |
| 1306 | .name = "SST 39SF020A", | 1309 | .name = "SST 39SF020A", |
| @@ -1412,6 +1415,18 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1412 | ERASEINFO(0x1000,256) | 1415 | ERASEINFO(0x1000,256) |
| 1413 | } | 1416 | } |
| 1414 | }, { | 1417 | }, { |
| 1418 | .mfr_id = MANUFACTURER_SST, | ||
| 1419 | .dev_id = SST36VF3203, | ||
| 1420 | .name = "SST 36VF3203", | ||
| 1421 | .devtypes = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8, | ||
| 1422 | .uaddr = MTD_UADDR_0x0AAA_0x0555, | ||
| 1423 | .dev_size = SIZE_4MiB, | ||
| 1424 | .cmd_set = P_ID_AMD_STD, | ||
| 1425 | .nr_regions = 1, | ||
| 1426 | .regions = { | ||
| 1427 | ERASEINFO(0x10000,64), | ||
| 1428 | } | ||
| 1429 | }, { | ||
| 1415 | .mfr_id = MANUFACTURER_ST, | 1430 | .mfr_id = MANUFACTURER_ST, |
| 1416 | .dev_id = M29F800AB, | 1431 | .dev_id = M29F800AB, |
| 1417 | .name = "ST M29F800AB", | 1432 | .name = "ST M29F800AB", |
| @@ -1426,7 +1441,7 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1426 | ERASEINFO(0x08000,1), | 1441 | ERASEINFO(0x08000,1), |
| 1427 | ERASEINFO(0x10000,15), | 1442 | ERASEINFO(0x10000,15), |
| 1428 | } | 1443 | } |
| 1429 | }, { | 1444 | }, { |
| 1430 | .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */ | 1445 | .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */ |
| 1431 | .dev_id = M29W800DT, | 1446 | .dev_id = M29W800DT, |
| 1432 | .name = "ST M29W800DT", | 1447 | .name = "ST M29W800DT", |
| @@ -1456,6 +1471,36 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1456 | ERASEINFO(0x08000,1), | 1471 | ERASEINFO(0x08000,1), |
| 1457 | ERASEINFO(0x10000,15) | 1472 | ERASEINFO(0x10000,15) |
| 1458 | } | 1473 | } |
| 1474 | }, { | ||
| 1475 | .mfr_id = MANUFACTURER_ST, | ||
| 1476 | .dev_id = M29W400DT, | ||
| 1477 | .name = "ST M29W400DT", | ||
| 1478 | .devtypes = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8, | ||
| 1479 | .uaddr = MTD_UADDR_0x0AAA_0x0555, | ||
| 1480 | .dev_size = SIZE_512KiB, | ||
| 1481 | .cmd_set = P_ID_AMD_STD, | ||
| 1482 | .nr_regions = 4, | ||
| 1483 | .regions = { | ||
| 1484 | ERASEINFO(0x04000,7), | ||
| 1485 | ERASEINFO(0x02000,1), | ||
| 1486 | ERASEINFO(0x08000,2), | ||
| 1487 | ERASEINFO(0x10000,1) | ||
| 1488 | } | ||
| 1489 | }, { | ||
| 1490 | .mfr_id = MANUFACTURER_ST, | ||
| 1491 | .dev_id = M29W400DB, | ||
| 1492 | .name = "ST M29W400DB", | ||
| 1493 | .devtypes = CFI_DEVICETYPE_X16|CFI_DEVICETYPE_X8, | ||
| 1494 | .uaddr = MTD_UADDR_0x0AAA_0x0555, | ||
| 1495 | .dev_size = SIZE_512KiB, | ||
| 1496 | .cmd_set = P_ID_AMD_STD, | ||
| 1497 | .nr_regions = 4, | ||
| 1498 | .regions = { | ||
| 1499 | ERASEINFO(0x04000,1), | ||
| 1500 | ERASEINFO(0x02000,2), | ||
| 1501 | ERASEINFO(0x08000,1), | ||
| 1502 | ERASEINFO(0x10000,7) | ||
| 1503 | } | ||
| 1459 | }, { | 1504 | }, { |
| 1460 | .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */ | 1505 | .mfr_id = MANUFACTURER_ST, /* FIXME - CFI device? */ |
| 1461 | .dev_id = M29W160DT, | 1506 | .dev_id = M29W160DT, |
| @@ -1486,7 +1531,7 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1486 | ERASEINFO(0x08000,1), | 1531 | ERASEINFO(0x08000,1), |
| 1487 | ERASEINFO(0x10000,31) | 1532 | ERASEINFO(0x10000,31) |
| 1488 | } | 1533 | } |
| 1489 | }, { | 1534 | }, { |
| 1490 | .mfr_id = MANUFACTURER_ST, | 1535 | .mfr_id = MANUFACTURER_ST, |
| 1491 | .dev_id = M29W040B, | 1536 | .dev_id = M29W040B, |
| 1492 | .name = "ST M29W040B", | 1537 | .name = "ST M29W040B", |
| @@ -1498,7 +1543,7 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1498 | .regions = { | 1543 | .regions = { |
| 1499 | ERASEINFO(0x10000,8), | 1544 | ERASEINFO(0x10000,8), |
| 1500 | } | 1545 | } |
| 1501 | }, { | 1546 | }, { |
| 1502 | .mfr_id = MANUFACTURER_ST, | 1547 | .mfr_id = MANUFACTURER_ST, |
| 1503 | .dev_id = M50FW040, | 1548 | .dev_id = M50FW040, |
| 1504 | .name = "ST M50FW040", | 1549 | .name = "ST M50FW040", |
| @@ -1510,7 +1555,7 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1510 | .regions = { | 1555 | .regions = { |
| 1511 | ERASEINFO(0x10000,8), | 1556 | ERASEINFO(0x10000,8), |
| 1512 | } | 1557 | } |
| 1513 | }, { | 1558 | }, { |
| 1514 | .mfr_id = MANUFACTURER_ST, | 1559 | .mfr_id = MANUFACTURER_ST, |
| 1515 | .dev_id = M50FW080, | 1560 | .dev_id = M50FW080, |
| 1516 | .name = "ST M50FW080", | 1561 | .name = "ST M50FW080", |
| @@ -1522,7 +1567,7 @@ static const struct amd_flash_info jedec_table[] = { | |||
| 1522 | .regions = { | 1567 | .regions = { |
| 1523 | ERASEINFO(0x10000,16), | 1568 | ERASEINFO(0x10000,16), |
| 1524 | } | 1569 | } |
| 1525 | }, { | 1570 | }, { |
| 1526 | .mfr_id = MANUFACTURER_ST, | 1571 | .mfr_id = MANUFACTURER_ST, |
| 1527 | .dev_id = M50FW016, | 1572 | .dev_id = M50FW016, |
| 1528 | .name = "ST M50FW016", | 1573 | .name = "ST M50FW016", |
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c index b44292abd9f7..e472a0e9de9d 100644 --- a/drivers/mtd/cmdlinepart.c +++ b/drivers/mtd/cmdlinepart.c | |||
| @@ -119,7 +119,8 @@ static struct mtd_partition * newpart(char *s, | |||
| 119 | char *p; | 119 | char *p; |
| 120 | 120 | ||
| 121 | name = ++s; | 121 | name = ++s; |
| 122 | if ((p = strchr(name, delim)) == 0) | 122 | p = strchr(name, delim); |
| 123 | if (!p) | ||
| 123 | { | 124 | { |
| 124 | printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim); | 125 | printk(KERN_ERR ERRP "no closing %c found in partition name\n", delim); |
| 125 | return NULL; | 126 | return NULL; |
| @@ -159,9 +160,10 @@ static struct mtd_partition * newpart(char *s, | |||
| 159 | return NULL; | 160 | return NULL; |
| 160 | } | 161 | } |
| 161 | /* more partitions follow, parse them */ | 162 | /* more partitions follow, parse them */ |
| 162 | if ((parts = newpart(s + 1, &s, num_parts, | 163 | parts = newpart(s + 1, &s, num_parts, this_part + 1, |
| 163 | this_part + 1, &extra_mem, extra_mem_size)) == 0) | 164 | &extra_mem, extra_mem_size); |
| 164 | return NULL; | 165 | if (!parts) |
| 166 | return NULL; | ||
| 165 | } | 167 | } |
| 166 | else | 168 | else |
| 167 | { /* this is the last partition: allocate space for all */ | 169 | { /* this is the last partition: allocate space for all */ |
| @@ -308,9 +310,6 @@ static int parse_cmdline_partitions(struct mtd_info *master, | |||
| 308 | struct cmdline_mtd_partition *part; | 310 | struct cmdline_mtd_partition *part; |
| 309 | char *mtd_id = master->name; | 311 | char *mtd_id = master->name; |
| 310 | 312 | ||
| 311 | if(!cmdline) | ||
| 312 | return -EINVAL; | ||
| 313 | |||
| 314 | /* parse command line */ | 313 | /* parse command line */ |
| 315 | if (!cmdline_parsed) | 314 | if (!cmdline_parsed) |
| 316 | mtdpart_setup_real(cmdline); | 315 | mtdpart_setup_real(cmdline); |
| @@ -341,7 +340,7 @@ static int parse_cmdline_partitions(struct mtd_info *master, | |||
| 341 | return part->num_parts; | 340 | return part->num_parts; |
| 342 | } | 341 | } |
| 343 | } | 342 | } |
| 344 | return -EINVAL; | 343 | return 0; |
| 345 | } | 344 | } |
| 346 | 345 | ||
| 347 | 346 | ||
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 811d56fd890f..35ed1103dbb2 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
| @@ -77,6 +77,13 @@ config MTD_M25P80 | |||
| 77 | if you want to specify device partitioning or to use a device which | 77 | if you want to specify device partitioning or to use a device which |
| 78 | doesn't support the JEDEC ID instruction. | 78 | doesn't support the JEDEC ID instruction. |
| 79 | 79 | ||
| 80 | config M25PXX_USE_FAST_READ | ||
| 81 | bool "Use FAST_READ OPCode allowing SPI CLK <= 50MHz" | ||
| 82 | depends on MTD_M25P80 | ||
| 83 | default y | ||
| 84 | help | ||
| 85 | This option enables FAST_READ access supported by ST M25Pxx. | ||
| 86 | |||
| 80 | config MTD_SLRAM | 87 | config MTD_SLRAM |
| 81 | tristate "Uncached system RAM" | 88 | tristate "Uncached system RAM" |
| 82 | help | 89 | help |
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index ad1880c67518..519d942e7940 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
| @@ -305,7 +305,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
| 305 | } | 305 | } |
| 306 | list_add(&dev->list, &blkmtd_device_list); | 306 | list_add(&dev->list, &blkmtd_device_list); |
| 307 | INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index, | 307 | INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index, |
| 308 | dev->mtd.name + strlen("blkmtd: "), | 308 | dev->mtd.name + strlen("block2mtd: "), |
| 309 | dev->mtd.erasesize >> 10, dev->mtd.erasesize); | 309 | dev->mtd.erasesize >> 10, dev->mtd.erasesize); |
| 310 | return dev; | 310 | return dev; |
| 311 | 311 | ||
| @@ -366,9 +366,9 @@ static inline void kill_final_newline(char *str) | |||
| 366 | } | 366 | } |
| 367 | 367 | ||
| 368 | 368 | ||
| 369 | #define parse_err(fmt, args...) do { \ | 369 | #define parse_err(fmt, args...) do { \ |
| 370 | ERROR("block2mtd: " fmt "\n", ## args); \ | 370 | ERROR(fmt, ## args); \ |
| 371 | return 0; \ | 371 | return 0; \ |
| 372 | } while (0) | 372 | } while (0) |
| 373 | 373 | ||
| 374 | #ifndef MODULE | 374 | #ifndef MODULE |
| @@ -473,7 +473,7 @@ static void __devexit block2mtd_exit(void) | |||
| 473 | block2mtd_sync(&dev->mtd); | 473 | block2mtd_sync(&dev->mtd); |
| 474 | del_mtd_device(&dev->mtd); | 474 | del_mtd_device(&dev->mtd); |
| 475 | INFO("mtd%d: [%s] removed", dev->mtd.index, | 475 | INFO("mtd%d: [%s] removed", dev->mtd.index, |
| 476 | dev->mtd.name + strlen("blkmtd: ")); | 476 | dev->mtd.name + strlen("block2mtd: ")); |
| 477 | list_del(&dev->list); | 477 | list_del(&dev->list); |
| 478 | block2mtd_free_device(dev); | 478 | block2mtd_free_device(dev); |
| 479 | } | 479 | } |
diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c index 99fd210feaec..1d324e5c412d 100644 --- a/drivers/mtd/devices/lart.c +++ b/drivers/mtd/devices/lart.c | |||
| @@ -275,7 +275,7 @@ static __u8 read8 (__u32 offset) | |||
| 275 | { | 275 | { |
| 276 | volatile __u8 *data = (__u8 *) (FLASH_OFFSET + offset); | 276 | volatile __u8 *data = (__u8 *) (FLASH_OFFSET + offset); |
| 277 | #ifdef LART_DEBUG | 277 | #ifdef LART_DEBUG |
| 278 | printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.2x\n",__FUNCTION__,offset,*data); | 278 | printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.2x\n", __func__, offset, *data); |
| 279 | #endif | 279 | #endif |
| 280 | return (*data); | 280 | return (*data); |
| 281 | } | 281 | } |
| @@ -284,7 +284,7 @@ static __u32 read32 (__u32 offset) | |||
| 284 | { | 284 | { |
| 285 | volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset); | 285 | volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset); |
| 286 | #ifdef LART_DEBUG | 286 | #ifdef LART_DEBUG |
| 287 | printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.8x\n",__FUNCTION__,offset,*data); | 287 | printk (KERN_DEBUG "%s(): 0x%.8x -> 0x%.8x\n", __func__, offset, *data); |
| 288 | #endif | 288 | #endif |
| 289 | return (*data); | 289 | return (*data); |
| 290 | } | 290 | } |
| @@ -294,7 +294,7 @@ static void write32 (__u32 x,__u32 offset) | |||
| 294 | volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset); | 294 | volatile __u32 *data = (__u32 *) (FLASH_OFFSET + offset); |
| 295 | *data = x; | 295 | *data = x; |
| 296 | #ifdef LART_DEBUG | 296 | #ifdef LART_DEBUG |
| 297 | printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n",__FUNCTION__,offset,*data); | 297 | printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, *data); |
| 298 | #endif | 298 | #endif |
| 299 | } | 299 | } |
| 300 | 300 | ||
| @@ -337,7 +337,7 @@ static inline int erase_block (__u32 offset) | |||
| 337 | __u32 status; | 337 | __u32 status; |
| 338 | 338 | ||
| 339 | #ifdef LART_DEBUG | 339 | #ifdef LART_DEBUG |
| 340 | printk (KERN_DEBUG "%s(): 0x%.8x\n",__FUNCTION__,offset); | 340 | printk (KERN_DEBUG "%s(): 0x%.8x\n", __func__, offset); |
| 341 | #endif | 341 | #endif |
| 342 | 342 | ||
| 343 | /* erase and confirm */ | 343 | /* erase and confirm */ |
| @@ -371,7 +371,7 @@ static int flash_erase (struct mtd_info *mtd,struct erase_info *instr) | |||
| 371 | int i,first; | 371 | int i,first; |
| 372 | 372 | ||
| 373 | #ifdef LART_DEBUG | 373 | #ifdef LART_DEBUG |
| 374 | printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n",__FUNCTION__,instr->addr,instr->len); | 374 | printk (KERN_DEBUG "%s(addr = 0x%.8x, len = %d)\n", __func__, instr->addr, instr->len); |
| 375 | #endif | 375 | #endif |
| 376 | 376 | ||
| 377 | /* sanity checks */ | 377 | /* sanity checks */ |
| @@ -442,7 +442,7 @@ static int flash_erase (struct mtd_info *mtd,struct erase_info *instr) | |||
| 442 | static int flash_read (struct mtd_info *mtd,loff_t from,size_t len,size_t *retlen,u_char *buf) | 442 | static int flash_read (struct mtd_info *mtd,loff_t from,size_t len,size_t *retlen,u_char *buf) |
| 443 | { | 443 | { |
| 444 | #ifdef LART_DEBUG | 444 | #ifdef LART_DEBUG |
| 445 | printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) from,len); | 445 | printk (KERN_DEBUG "%s(from = 0x%.8x, len = %d)\n", __func__, (__u32)from, len); |
| 446 | #endif | 446 | #endif |
| 447 | 447 | ||
| 448 | /* sanity checks */ | 448 | /* sanity checks */ |
| @@ -488,7 +488,7 @@ static inline int write_dword (__u32 offset,__u32 x) | |||
| 488 | __u32 status; | 488 | __u32 status; |
| 489 | 489 | ||
| 490 | #ifdef LART_DEBUG | 490 | #ifdef LART_DEBUG |
| 491 | printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n",__FUNCTION__,offset,x); | 491 | printk (KERN_DEBUG "%s(): 0x%.8x <- 0x%.8x\n", __func__, offset, x); |
| 492 | #endif | 492 | #endif |
| 493 | 493 | ||
| 494 | /* setup writing */ | 494 | /* setup writing */ |
| @@ -524,7 +524,7 @@ static int flash_write (struct mtd_info *mtd,loff_t to,size_t len,size_t *retlen | |||
| 524 | int i,n; | 524 | int i,n; |
| 525 | 525 | ||
| 526 | #ifdef LART_DEBUG | 526 | #ifdef LART_DEBUG |
| 527 | printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n",__FUNCTION__,(__u32) to,len); | 527 | printk (KERN_DEBUG "%s(to = 0x%.8x, len = %d)\n", __func__, (__u32)to, len); |
| 528 | #endif | 528 | #endif |
| 529 | 529 | ||
| 530 | *retlen = 0; | 530 | *retlen = 0; |
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c index 98df5bcc02f3..25efd331ef28 100644 --- a/drivers/mtd/devices/m25p80.c +++ b/drivers/mtd/devices/m25p80.c | |||
| @@ -33,7 +33,7 @@ | |||
| 33 | /* Flash opcodes. */ | 33 | /* Flash opcodes. */ |
| 34 | #define OPCODE_WREN 0x06 /* Write enable */ | 34 | #define OPCODE_WREN 0x06 /* Write enable */ |
| 35 | #define OPCODE_RDSR 0x05 /* Read status register */ | 35 | #define OPCODE_RDSR 0x05 /* Read status register */ |
| 36 | #define OPCODE_READ 0x03 /* Read data bytes (low frequency) */ | 36 | #define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */ |
| 37 | #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ | 37 | #define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */ |
| 38 | #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ | 38 | #define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */ |
| 39 | #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ | 39 | #define OPCODE_BE_4K 0x20 /* Erase 4KiB block */ |
| @@ -52,7 +52,15 @@ | |||
| 52 | 52 | ||
| 53 | /* Define max times to check status register before we give up. */ | 53 | /* Define max times to check status register before we give up. */ |
| 54 | #define MAX_READY_WAIT_COUNT 100000 | 54 | #define MAX_READY_WAIT_COUNT 100000 |
| 55 | #define CMD_SIZE 4 | ||
| 55 | 56 | ||
| 57 | #ifdef CONFIG_M25PXX_USE_FAST_READ | ||
| 58 | #define OPCODE_READ OPCODE_FAST_READ | ||
| 59 | #define FAST_READ_DUMMY_BYTE 1 | ||
| 60 | #else | ||
| 61 | #define OPCODE_READ OPCODE_NORM_READ | ||
| 62 | #define FAST_READ_DUMMY_BYTE 0 | ||
| 63 | #endif | ||
| 56 | 64 | ||
| 57 | #ifdef CONFIG_MTD_PARTITIONS | 65 | #ifdef CONFIG_MTD_PARTITIONS |
| 58 | #define mtd_has_partitions() (1) | 66 | #define mtd_has_partitions() (1) |
| @@ -68,7 +76,7 @@ struct m25p { | |||
| 68 | struct mtd_info mtd; | 76 | struct mtd_info mtd; |
| 69 | unsigned partitioned:1; | 77 | unsigned partitioned:1; |
| 70 | u8 erase_opcode; | 78 | u8 erase_opcode; |
| 71 | u8 command[4]; | 79 | u8 command[CMD_SIZE + FAST_READ_DUMMY_BYTE]; |
| 72 | }; | 80 | }; |
| 73 | 81 | ||
| 74 | static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) | 82 | static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd) |
| @@ -151,7 +159,7 @@ static int wait_till_ready(struct m25p *flash) | |||
| 151 | static int erase_sector(struct m25p *flash, u32 offset) | 159 | static int erase_sector(struct m25p *flash, u32 offset) |
| 152 | { | 160 | { |
| 153 | DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n", | 161 | DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n", |
| 154 | flash->spi->dev.bus_id, __FUNCTION__, | 162 | flash->spi->dev.bus_id, __func__, |
| 155 | flash->mtd.erasesize / 1024, offset); | 163 | flash->mtd.erasesize / 1024, offset); |
| 156 | 164 | ||
| 157 | /* Wait until finished previous write command. */ | 165 | /* Wait until finished previous write command. */ |
| @@ -167,7 +175,7 @@ static int erase_sector(struct m25p *flash, u32 offset) | |||
| 167 | flash->command[2] = offset >> 8; | 175 | flash->command[2] = offset >> 8; |
| 168 | flash->command[3] = offset; | 176 | flash->command[3] = offset; |
| 169 | 177 | ||
| 170 | spi_write(flash->spi, flash->command, sizeof(flash->command)); | 178 | spi_write(flash->spi, flash->command, CMD_SIZE); |
| 171 | 179 | ||
| 172 | return 0; | 180 | return 0; |
| 173 | } | 181 | } |
| @@ -188,7 +196,7 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
| 188 | u32 addr,len; | 196 | u32 addr,len; |
| 189 | 197 | ||
| 190 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n", | 198 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %d\n", |
| 191 | flash->spi->dev.bus_id, __FUNCTION__, "at", | 199 | flash->spi->dev.bus_id, __func__, "at", |
| 192 | (u32)instr->addr, instr->len); | 200 | (u32)instr->addr, instr->len); |
| 193 | 201 | ||
| 194 | /* sanity checks */ | 202 | /* sanity checks */ |
| @@ -240,7 +248,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 240 | struct spi_message m; | 248 | struct spi_message m; |
| 241 | 249 | ||
| 242 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | 250 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", |
| 243 | flash->spi->dev.bus_id, __FUNCTION__, "from", | 251 | flash->spi->dev.bus_id, __func__, "from", |
| 244 | (u32)from, len); | 252 | (u32)from, len); |
| 245 | 253 | ||
| 246 | /* sanity checks */ | 254 | /* sanity checks */ |
| @@ -253,8 +261,12 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 253 | spi_message_init(&m); | 261 | spi_message_init(&m); |
| 254 | memset(t, 0, (sizeof t)); | 262 | memset(t, 0, (sizeof t)); |
| 255 | 263 | ||
| 264 | /* NOTE: | ||
| 265 | * OPCODE_FAST_READ (if available) is faster. | ||
| 266 | * Should add 1 byte DUMMY_BYTE. | ||
| 267 | */ | ||
| 256 | t[0].tx_buf = flash->command; | 268 | t[0].tx_buf = flash->command; |
| 257 | t[0].len = sizeof(flash->command); | 269 | t[0].len = CMD_SIZE + FAST_READ_DUMMY_BYTE; |
| 258 | spi_message_add_tail(&t[0], &m); | 270 | spi_message_add_tail(&t[0], &m); |
| 259 | 271 | ||
| 260 | t[1].rx_buf = buf; | 272 | t[1].rx_buf = buf; |
| @@ -287,7 +299,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len, | |||
| 287 | 299 | ||
| 288 | spi_sync(flash->spi, &m); | 300 | spi_sync(flash->spi, &m); |
| 289 | 301 | ||
| 290 | *retlen = m.actual_length - sizeof(flash->command); | 302 | *retlen = m.actual_length - CMD_SIZE - FAST_READ_DUMMY_BYTE; |
| 291 | 303 | ||
| 292 | mutex_unlock(&flash->lock); | 304 | mutex_unlock(&flash->lock); |
| 293 | 305 | ||
| @@ -308,7 +320,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 308 | struct spi_message m; | 320 | struct spi_message m; |
| 309 | 321 | ||
| 310 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", | 322 | DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n", |
| 311 | flash->spi->dev.bus_id, __FUNCTION__, "to", | 323 | flash->spi->dev.bus_id, __func__, "to", |
| 312 | (u32)to, len); | 324 | (u32)to, len); |
| 313 | 325 | ||
| 314 | if (retlen) | 326 | if (retlen) |
| @@ -325,7 +337,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 325 | memset(t, 0, (sizeof t)); | 337 | memset(t, 0, (sizeof t)); |
| 326 | 338 | ||
| 327 | t[0].tx_buf = flash->command; | 339 | t[0].tx_buf = flash->command; |
| 328 | t[0].len = sizeof(flash->command); | 340 | t[0].len = CMD_SIZE; |
| 329 | spi_message_add_tail(&t[0], &m); | 341 | spi_message_add_tail(&t[0], &m); |
| 330 | 342 | ||
| 331 | t[1].tx_buf = buf; | 343 | t[1].tx_buf = buf; |
| @@ -354,7 +366,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 354 | 366 | ||
| 355 | spi_sync(flash->spi, &m); | 367 | spi_sync(flash->spi, &m); |
| 356 | 368 | ||
| 357 | *retlen = m.actual_length - sizeof(flash->command); | 369 | *retlen = m.actual_length - CMD_SIZE; |
| 358 | } else { | 370 | } else { |
| 359 | u32 i; | 371 | u32 i; |
| 360 | 372 | ||
| @@ -364,7 +376,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 364 | t[1].len = page_size; | 376 | t[1].len = page_size; |
| 365 | spi_sync(flash->spi, &m); | 377 | spi_sync(flash->spi, &m); |
| 366 | 378 | ||
| 367 | *retlen = m.actual_length - sizeof(flash->command); | 379 | *retlen = m.actual_length - CMD_SIZE; |
| 368 | 380 | ||
| 369 | /* write everything in PAGESIZE chunks */ | 381 | /* write everything in PAGESIZE chunks */ |
| 370 | for (i = page_size; i < len; i += page_size) { | 382 | for (i = page_size; i < len; i += page_size) { |
| @@ -387,8 +399,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 387 | spi_sync(flash->spi, &m); | 399 | spi_sync(flash->spi, &m); |
| 388 | 400 | ||
| 389 | if (retlen) | 401 | if (retlen) |
| 390 | *retlen += m.actual_length | 402 | *retlen += m.actual_length - CMD_SIZE; |
| 391 | - sizeof(flash->command); | ||
| 392 | } | 403 | } |
| 393 | } | 404 | } |
| 394 | 405 | ||
| @@ -435,6 +446,7 @@ static struct flash_info __devinitdata m25p_data [] = { | |||
| 435 | { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, }, | 446 | { "at25fs040", 0x1f6604, 64 * 1024, 8, SECT_4K, }, |
| 436 | 447 | ||
| 437 | { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, }, | 448 | { "at25df041a", 0x1f4401, 64 * 1024, 8, SECT_4K, }, |
| 449 | { "at25df641", 0x1f4800, 64 * 1024, 128, SECT_4K, }, | ||
| 438 | 450 | ||
| 439 | { "at26f004", 0x1f0400, 64 * 1024, 8, SECT_4K, }, | 451 | { "at26f004", 0x1f0400, 64 * 1024, 8, SECT_4K, }, |
| 440 | { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, }, | 452 | { "at26df081a", 0x1f4501, 64 * 1024, 16, SECT_4K, }, |
diff --git a/drivers/mtd/devices/mtdram.c b/drivers/mtd/devices/mtdram.c index e427c82d5f4c..bf485ff49457 100644 --- a/drivers/mtd/devices/mtdram.c +++ b/drivers/mtd/devices/mtdram.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
| 18 | #include <linux/mtd/compatmac.h> | 18 | #include <linux/mtd/compatmac.h> |
| 19 | #include <linux/mtd/mtd.h> | 19 | #include <linux/mtd/mtd.h> |
| 20 | #include <linux/mtd/mtdram.h> | ||
| 20 | 21 | ||
| 21 | static unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE; | 22 | static unsigned long total_size = CONFIG_MTDRAM_TOTAL_SIZE; |
| 22 | static unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE; | 23 | static unsigned long erase_size = CONFIG_MTDRAM_ERASE_SIZE; |
diff --git a/drivers/mtd/devices/phram.c b/drivers/mtd/devices/phram.c index 180298b92a7a..5f960182da95 100644 --- a/drivers/mtd/devices/phram.c +++ b/drivers/mtd/devices/phram.c | |||
| @@ -282,7 +282,7 @@ static int phram_setup(const char *val, struct kernel_param *kp) | |||
| 282 | } | 282 | } |
| 283 | 283 | ||
| 284 | module_param_call(phram, phram_setup, NULL, NULL, 000); | 284 | module_param_call(phram, phram_setup, NULL, NULL, 000); |
| 285 | MODULE_PARM_DESC(phram,"Memory region to map. \"map=<name>,<start>,<length>\""); | 285 | MODULE_PARM_DESC(phram, "Memory region to map. \"phram=<name>,<start>,<length>\""); |
| 286 | 286 | ||
| 287 | 287 | ||
| 288 | static int __init init_phram(void) | 288 | static int __init init_phram(void) |
diff --git a/drivers/mtd/ftl.c b/drivers/mtd/ftl.c index c815d0f38577..4a79b187b568 100644 --- a/drivers/mtd/ftl.c +++ b/drivers/mtd/ftl.c | |||
| @@ -136,8 +136,6 @@ typedef struct partition_t { | |||
| 136 | #endif | 136 | #endif |
| 137 | } partition_t; | 137 | } partition_t; |
| 138 | 138 | ||
| 139 | void ftl_freepart(partition_t *part); | ||
| 140 | |||
| 141 | /* Partition state flags */ | 139 | /* Partition state flags */ |
| 142 | #define FTL_FORMATTED 0x01 | 140 | #define FTL_FORMATTED 0x01 |
| 143 | 141 | ||
| @@ -1014,7 +1012,7 @@ static int ftl_writesect(struct mtd_blktrans_dev *dev, | |||
| 1014 | 1012 | ||
| 1015 | /*====================================================================*/ | 1013 | /*====================================================================*/ |
| 1016 | 1014 | ||
| 1017 | void ftl_freepart(partition_t *part) | 1015 | static void ftl_freepart(partition_t *part) |
| 1018 | { | 1016 | { |
| 1019 | vfree(part->VirtualBlockMap); | 1017 | vfree(part->VirtualBlockMap); |
| 1020 | part->VirtualBlockMap = NULL; | 1018 | part->VirtualBlockMap = NULL; |
| @@ -1069,7 +1067,7 @@ static void ftl_remove_dev(struct mtd_blktrans_dev *dev) | |||
| 1069 | kfree(dev); | 1067 | kfree(dev); |
| 1070 | } | 1068 | } |
| 1071 | 1069 | ||
| 1072 | struct mtd_blktrans_ops ftl_tr = { | 1070 | static struct mtd_blktrans_ops ftl_tr = { |
| 1073 | .name = "ftl", | 1071 | .name = "ftl", |
| 1074 | .major = FTL_MAJOR, | 1072 | .major = FTL_MAJOR, |
| 1075 | .part_bits = PART_BITS, | 1073 | .part_bits = PART_BITS, |
diff --git a/drivers/mtd/inftlmount.c b/drivers/mtd/inftlmount.c index b8917beeb650..c551d2f0779c 100644 --- a/drivers/mtd/inftlmount.c +++ b/drivers/mtd/inftlmount.c | |||
| @@ -41,11 +41,6 @@ | |||
| 41 | 41 | ||
| 42 | char inftlmountrev[]="$Revision: 1.18 $"; | 42 | char inftlmountrev[]="$Revision: 1.18 $"; |
| 43 | 43 | ||
| 44 | extern int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, | ||
| 45 | size_t *retlen, uint8_t *buf); | ||
| 46 | extern int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, | ||
| 47 | size_t *retlen, uint8_t *buf); | ||
| 48 | |||
| 49 | /* | 44 | /* |
| 50 | * find_boot_record: Find the INFTL Media Header and its Spare copy which | 45 | * find_boot_record: Find the INFTL Media Header and its Spare copy which |
| 51 | * contains the various device information of the INFTL partition and | 46 | * contains the various device information of the INFTL partition and |
diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 12c253664eb2..1bd69aa9e22a 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig | |||
| @@ -21,6 +21,9 @@ config MTD_PHYSMAP | |||
| 21 | particular board as well as the bus width, either statically | 21 | particular board as well as the bus width, either statically |
| 22 | with config options or at run-time. | 22 | with config options or at run-time. |
| 23 | 23 | ||
| 24 | To compile this driver as a module, choose M here: the | ||
| 25 | module will be called physmap. | ||
| 26 | |||
| 24 | config MTD_PHYSMAP_START | 27 | config MTD_PHYSMAP_START |
| 25 | hex "Physical start address of flash mapping" | 28 | hex "Physical start address of flash mapping" |
| 26 | depends on MTD_PHYSMAP | 29 | depends on MTD_PHYSMAP |
diff --git a/drivers/mtd/maps/bast-flash.c b/drivers/mtd/maps/bast-flash.c index fc3b2672d1e2..1f492062f8ca 100644 --- a/drivers/mtd/maps/bast-flash.c +++ b/drivers/mtd/maps/bast-flash.c | |||
| @@ -137,7 +137,7 @@ static int bast_flash_probe(struct platform_device *pdev) | |||
| 137 | if (info->map.size > AREA_MAXSIZE) | 137 | if (info->map.size > AREA_MAXSIZE) |
| 138 | info->map.size = AREA_MAXSIZE; | 138 | info->map.size = AREA_MAXSIZE; |
| 139 | 139 | ||
| 140 | pr_debug("%s: area %08lx, size %ld\n", __FUNCTION__, | 140 | pr_debug("%s: area %08lx, size %ld\n", __func__, |
| 141 | info->map.phys, info->map.size); | 141 | info->map.phys, info->map.size); |
| 142 | 142 | ||
| 143 | info->area = request_mem_region(res->start, info->map.size, | 143 | info->area = request_mem_region(res->start, info->map.size, |
| @@ -149,7 +149,7 @@ static int bast_flash_probe(struct platform_device *pdev) | |||
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | info->map.virt = ioremap(res->start, info->map.size); | 151 | info->map.virt = ioremap(res->start, info->map.size); |
| 152 | pr_debug("%s: virt at %08x\n", __FUNCTION__, (int)info->map.virt); | 152 | pr_debug("%s: virt at %08x\n", __func__, (int)info->map.virt); |
| 153 | 153 | ||
| 154 | if (info->map.virt == 0) { | 154 | if (info->map.virt == 0) { |
| 155 | printk(KERN_ERR PFX "failed to ioremap() region\n"); | 155 | printk(KERN_ERR PFX "failed to ioremap() region\n"); |
| @@ -223,3 +223,4 @@ module_exit(bast_flash_exit); | |||
| 223 | MODULE_LICENSE("GPL"); | 223 | MODULE_LICENSE("GPL"); |
| 224 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | 224 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); |
| 225 | MODULE_DESCRIPTION("BAST MTD Map driver"); | 225 | MODULE_DESCRIPTION("BAST MTD Map driver"); |
| 226 | MODULE_ALIAS("platform:bast-nor"); | ||
diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c index 688ef495888a..59d8fb49270a 100644 --- a/drivers/mtd/maps/ck804xrom.c +++ b/drivers/mtd/maps/ck804xrom.c | |||
| @@ -28,6 +28,9 @@ | |||
| 28 | 28 | ||
| 29 | #define ROM_PROBE_STEP_SIZE (64*1024) | 29 | #define ROM_PROBE_STEP_SIZE (64*1024) |
| 30 | 30 | ||
| 31 | #define DEV_CK804 1 | ||
| 32 | #define DEV_MCP55 2 | ||
| 33 | |||
| 31 | struct ck804xrom_window { | 34 | struct ck804xrom_window { |
| 32 | void __iomem *virt; | 35 | void __iomem *virt; |
| 33 | unsigned long phys; | 36 | unsigned long phys; |
| @@ -45,8 +48,9 @@ struct ck804xrom_map_info { | |||
| 45 | char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN]; | 48 | char map_name[sizeof(MOD_NAME) + 2 + ADDRESS_NAME_LEN]; |
| 46 | }; | 49 | }; |
| 47 | 50 | ||
| 48 | 51 | /* | |
| 49 | /* The 2 bits controlling the window size are often set to allow reading | 52 | * The following applies to ck804 only: |
| 53 | * The 2 bits controlling the window size are often set to allow reading | ||
| 50 | * the BIOS, but too small to allow writing, since the lock registers are | 54 | * the BIOS, but too small to allow writing, since the lock registers are |
| 51 | * 4MiB lower in the address space than the data. | 55 | * 4MiB lower in the address space than the data. |
| 52 | * | 56 | * |
| @@ -58,10 +62,17 @@ struct ck804xrom_map_info { | |||
| 58 | * If only the 7 Bit is set, it is a 4MiB window. Otherwise, a | 62 | * If only the 7 Bit is set, it is a 4MiB window. Otherwise, a |
| 59 | * 64KiB window. | 63 | * 64KiB window. |
| 60 | * | 64 | * |
| 65 | * The following applies to mcp55 only: | ||
| 66 | * The 15 bits controlling the window size are distributed as follows: | ||
| 67 | * byte @0x88: bit 0..7 | ||
| 68 | * byte @0x8c: bit 8..15 | ||
| 69 | * word @0x90: bit 16..30 | ||
| 70 | * If all bits are enabled, we have a 16? MiB window | ||
| 71 | * Please set win_size_bits to 0x7fffffff if you actually want to do something | ||
| 61 | */ | 72 | */ |
| 62 | static uint win_size_bits = 0; | 73 | static uint win_size_bits = 0; |
| 63 | module_param(win_size_bits, uint, 0); | 74 | module_param(win_size_bits, uint, 0); |
| 64 | MODULE_PARM_DESC(win_size_bits, "ROM window size bits override for 0x88 byte, normally set by BIOS."); | 75 | MODULE_PARM_DESC(win_size_bits, "ROM window size bits override, normally set by BIOS."); |
| 65 | 76 | ||
| 66 | static struct ck804xrom_window ck804xrom_window = { | 77 | static struct ck804xrom_window ck804xrom_window = { |
| 67 | .maps = LIST_HEAD_INIT(ck804xrom_window.maps), | 78 | .maps = LIST_HEAD_INIT(ck804xrom_window.maps), |
| @@ -102,10 +113,11 @@ static void ck804xrom_cleanup(struct ck804xrom_window *window) | |||
| 102 | 113 | ||
| 103 | 114 | ||
| 104 | static int __devinit ck804xrom_init_one (struct pci_dev *pdev, | 115 | static int __devinit ck804xrom_init_one (struct pci_dev *pdev, |
| 105 | const struct pci_device_id *ent) | 116 | const struct pci_device_id *ent) |
| 106 | { | 117 | { |
| 107 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; | 118 | static char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL }; |
| 108 | u8 byte; | 119 | u8 byte; |
| 120 | u16 word; | ||
| 109 | struct ck804xrom_window *window = &ck804xrom_window; | 121 | struct ck804xrom_window *window = &ck804xrom_window; |
| 110 | struct ck804xrom_map_info *map = NULL; | 122 | struct ck804xrom_map_info *map = NULL; |
| 111 | unsigned long map_top; | 123 | unsigned long map_top; |
| @@ -113,26 +125,42 @@ static int __devinit ck804xrom_init_one (struct pci_dev *pdev, | |||
| 113 | /* Remember the pci dev I find the window in */ | 125 | /* Remember the pci dev I find the window in */ |
| 114 | window->pdev = pci_dev_get(pdev); | 126 | window->pdev = pci_dev_get(pdev); |
| 115 | 127 | ||
| 116 | /* Enable the selected rom window. This is often incorrectly | 128 | switch (ent->driver_data) { |
| 117 | * set up by the BIOS, and the 4MiB offset for the lock registers | 129 | case DEV_CK804: |
| 118 | * requires the full 5MiB of window space. | 130 | /* Enable the selected rom window. This is often incorrectly |
| 119 | * | 131 | * set up by the BIOS, and the 4MiB offset for the lock registers |
| 120 | * This 'write, then read' approach leaves the bits for | 132 | * requires the full 5MiB of window space. |
| 121 | * other uses of the hardware info. | 133 | * |
| 122 | */ | 134 | * This 'write, then read' approach leaves the bits for |
| 123 | pci_read_config_byte(pdev, 0x88, &byte); | 135 | * other uses of the hardware info. |
| 124 | pci_write_config_byte(pdev, 0x88, byte | win_size_bits ); | 136 | */ |
| 125 | 137 | pci_read_config_byte(pdev, 0x88, &byte); | |
| 126 | 138 | pci_write_config_byte(pdev, 0x88, byte | win_size_bits ); | |
| 127 | /* Assume the rom window is properly setup, and find it's size */ | 139 | |
| 128 | pci_read_config_byte(pdev, 0x88, &byte); | 140 | /* Assume the rom window is properly setup, and find it's size */ |
| 129 | 141 | pci_read_config_byte(pdev, 0x88, &byte); | |
| 130 | if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) | 142 | |
| 131 | window->phys = 0xffb00000; /* 5MiB */ | 143 | if ((byte & ((1<<7)|(1<<6))) == ((1<<7)|(1<<6))) |
| 132 | else if ((byte & (1<<7)) == (1<<7)) | 144 | window->phys = 0xffb00000; /* 5MiB */ |
| 133 | window->phys = 0xffc00000; /* 4MiB */ | 145 | else if ((byte & (1<<7)) == (1<<7)) |
| 134 | else | 146 | window->phys = 0xffc00000; /* 4MiB */ |
| 135 | window->phys = 0xffff0000; /* 64KiB */ | 147 | else |
| 148 | window->phys = 0xffff0000; /* 64KiB */ | ||
| 149 | break; | ||
| 150 | |||
| 151 | case DEV_MCP55: | ||
| 152 | pci_read_config_byte(pdev, 0x88, &byte); | ||
| 153 | pci_write_config_byte(pdev, 0x88, byte | (win_size_bits & 0xff)); | ||
| 154 | |||
| 155 | pci_read_config_byte(pdev, 0x8c, &byte); | ||
| 156 | pci_write_config_byte(pdev, 0x8c, byte | ((win_size_bits & 0xff00) >> 8)); | ||
| 157 | |||
| 158 | pci_read_config_word(pdev, 0x90, &word); | ||
| 159 | pci_write_config_word(pdev, 0x90, word | ((win_size_bits & 0x7fff0000) >> 16)); | ||
| 160 | |||
| 161 | window->phys = 0xff000000; /* 16MiB, hardcoded for now */ | ||
| 162 | break; | ||
| 163 | } | ||
| 136 | 164 | ||
| 137 | window->size = 0xffffffffUL - window->phys + 1UL; | 165 | window->size = 0xffffffffUL - window->phys + 1UL; |
| 138 | 166 | ||
| @@ -303,8 +331,15 @@ static void __devexit ck804xrom_remove_one (struct pci_dev *pdev) | |||
| 303 | } | 331 | } |
| 304 | 332 | ||
| 305 | static struct pci_device_id ck804xrom_pci_tbl[] = { | 333 | static struct pci_device_id ck804xrom_pci_tbl[] = { |
| 306 | { PCI_VENDOR_ID_NVIDIA, 0x0051, | 334 | { PCI_VENDOR_ID_NVIDIA, 0x0051, PCI_ANY_ID, PCI_ANY_ID, DEV_CK804 }, |
| 307 | PCI_ANY_ID, PCI_ANY_ID, }, /* nvidia ck804 */ | 335 | { PCI_VENDOR_ID_NVIDIA, 0x0360, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, |
| 336 | { PCI_VENDOR_ID_NVIDIA, 0x0361, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, | ||
| 337 | { PCI_VENDOR_ID_NVIDIA, 0x0362, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, | ||
| 338 | { PCI_VENDOR_ID_NVIDIA, 0x0363, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, | ||
| 339 | { PCI_VENDOR_ID_NVIDIA, 0x0364, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, | ||
| 340 | { PCI_VENDOR_ID_NVIDIA, 0x0365, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, | ||
| 341 | { PCI_VENDOR_ID_NVIDIA, 0x0366, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, | ||
| 342 | { PCI_VENDOR_ID_NVIDIA, 0x0367, PCI_ANY_ID, PCI_ANY_ID, DEV_MCP55 }, | ||
| 308 | { 0, } | 343 | { 0, } |
| 309 | }; | 344 | }; |
| 310 | 345 | ||
| @@ -332,7 +367,7 @@ static int __init init_ck804xrom(void) | |||
| 332 | break; | 367 | break; |
| 333 | } | 368 | } |
| 334 | if (pdev) { | 369 | if (pdev) { |
| 335 | retVal = ck804xrom_init_one(pdev, &ck804xrom_pci_tbl[0]); | 370 | retVal = ck804xrom_init_one(pdev, id); |
| 336 | pci_dev_put(pdev); | 371 | pci_dev_put(pdev); |
| 337 | return retVal; | 372 | return retVal; |
| 338 | } | 373 | } |
diff --git a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c index 6946d802e6f6..325c8880c437 100644 --- a/drivers/mtd/maps/integrator-flash.c +++ b/drivers/mtd/maps/integrator-flash.c | |||
| @@ -190,6 +190,7 @@ static struct platform_driver armflash_driver = { | |||
| 190 | .remove = armflash_remove, | 190 | .remove = armflash_remove, |
| 191 | .driver = { | 191 | .driver = { |
| 192 | .name = "armflash", | 192 | .name = "armflash", |
| 193 | .owner = THIS_MODULE, | ||
| 193 | }, | 194 | }, |
| 194 | }; | 195 | }; |
| 195 | 196 | ||
| @@ -209,3 +210,4 @@ module_exit(armflash_exit); | |||
| 209 | MODULE_AUTHOR("ARM Ltd"); | 210 | MODULE_AUTHOR("ARM Ltd"); |
| 210 | MODULE_DESCRIPTION("ARM Integrator CFI map driver"); | 211 | MODULE_DESCRIPTION("ARM Integrator CFI map driver"); |
| 211 | MODULE_LICENSE("GPL"); | 212 | MODULE_LICENSE("GPL"); |
| 213 | MODULE_ALIAS("platform:armflash"); | ||
diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c index c26488a1793a..c8396b8574c4 100644 --- a/drivers/mtd/maps/ixp2000.c +++ b/drivers/mtd/maps/ixp2000.c | |||
| @@ -253,6 +253,7 @@ static struct platform_driver ixp2000_flash_driver = { | |||
| 253 | .remove = ixp2000_flash_remove, | 253 | .remove = ixp2000_flash_remove, |
| 254 | .driver = { | 254 | .driver = { |
| 255 | .name = "IXP2000-Flash", | 255 | .name = "IXP2000-Flash", |
| 256 | .owner = THIS_MODULE, | ||
| 256 | }, | 257 | }, |
| 257 | }; | 258 | }; |
| 258 | 259 | ||
| @@ -270,4 +271,4 @@ module_init(ixp2000_flash_init); | |||
| 270 | module_exit(ixp2000_flash_exit); | 271 | module_exit(ixp2000_flash_exit); |
| 271 | MODULE_LICENSE("GPL"); | 272 | MODULE_LICENSE("GPL"); |
| 272 | MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>"); | 273 | MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>"); |
| 273 | 274 | MODULE_ALIAS("platform:IXP2000-Flash"); | |
diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index 7a828e3e6446..01f19a4714b5 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c | |||
| @@ -275,6 +275,7 @@ static struct platform_driver ixp4xx_flash_driver = { | |||
| 275 | .remove = ixp4xx_flash_remove, | 275 | .remove = ixp4xx_flash_remove, |
| 276 | .driver = { | 276 | .driver = { |
| 277 | .name = "IXP4XX-Flash", | 277 | .name = "IXP4XX-Flash", |
| 278 | .owner = THIS_MODULE, | ||
| 278 | }, | 279 | }, |
| 279 | }; | 280 | }; |
| 280 | 281 | ||
| @@ -295,3 +296,4 @@ module_exit(ixp4xx_flash_exit); | |||
| 295 | MODULE_LICENSE("GPL"); | 296 | MODULE_LICENSE("GPL"); |
| 296 | MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems"); | 297 | MODULE_DESCRIPTION("MTD map driver for Intel IXP4xx systems"); |
| 297 | MODULE_AUTHOR("Deepak Saxena"); | 298 | MODULE_AUTHOR("Deepak Saxena"); |
| 299 | MODULE_ALIAS("platform:IXP4XX-Flash"); | ||
diff --git a/drivers/mtd/maps/omap_nor.c b/drivers/mtd/maps/omap_nor.c index e8d9ae535673..240b0e2d095d 100644 --- a/drivers/mtd/maps/omap_nor.c +++ b/drivers/mtd/maps/omap_nor.c | |||
| @@ -70,7 +70,7 @@ static void omap_set_vpp(struct map_info *map, int enable) | |||
| 70 | } | 70 | } |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | static int __devinit omapflash_probe(struct platform_device *pdev) | 73 | static int __init omapflash_probe(struct platform_device *pdev) |
| 74 | { | 74 | { |
| 75 | int err; | 75 | int err; |
| 76 | struct omapflash_info *info; | 76 | struct omapflash_info *info; |
| @@ -130,7 +130,7 @@ out_free_info: | |||
| 130 | return err; | 130 | return err; |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | static int __devexit omapflash_remove(struct platform_device *pdev) | 133 | static int __exit omapflash_remove(struct platform_device *pdev) |
| 134 | { | 134 | { |
| 135 | struct omapflash_info *info = platform_get_drvdata(pdev); | 135 | struct omapflash_info *info = platform_get_drvdata(pdev); |
| 136 | 136 | ||
| @@ -152,16 +152,16 @@ static int __devexit omapflash_remove(struct platform_device *pdev) | |||
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | static struct platform_driver omapflash_driver = { | 154 | static struct platform_driver omapflash_driver = { |
| 155 | .probe = omapflash_probe, | 155 | .remove = __exit_p(omapflash_remove), |
| 156 | .remove = __devexit_p(omapflash_remove), | ||
| 157 | .driver = { | 156 | .driver = { |
| 158 | .name = "omapflash", | 157 | .name = "omapflash", |
| 158 | .owner = THIS_MODULE, | ||
| 159 | }, | 159 | }, |
| 160 | }; | 160 | }; |
| 161 | 161 | ||
| 162 | static int __init omapflash_init(void) | 162 | static int __init omapflash_init(void) |
| 163 | { | 163 | { |
| 164 | return platform_driver_register(&omapflash_driver); | 164 | return platform_driver_probe(&omapflash_driver, omapflash_probe); |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | static void __exit omapflash_exit(void) | 167 | static void __exit omapflash_exit(void) |
| @@ -174,4 +174,4 @@ module_exit(omapflash_exit); | |||
| 174 | 174 | ||
| 175 | MODULE_LICENSE("GPL"); | 175 | MODULE_LICENSE("GPL"); |
| 176 | MODULE_DESCRIPTION("MTD NOR map driver for TI OMAP boards"); | 176 | MODULE_DESCRIPTION("MTD NOR map driver for TI OMAP boards"); |
| 177 | 177 | MODULE_ALIAS("platform:omapflash"); | |
diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index eaeb56a4070a..1912d968718b 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c | |||
| @@ -33,7 +33,7 @@ MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy"); | |||
| 33 | #undef DEBUG | 33 | #undef DEBUG |
| 34 | #define DEBUG(n, format, arg...) \ | 34 | #define DEBUG(n, format, arg...) \ |
| 35 | if (n <= debug) { \ | 35 | if (n <= debug) { \ |
| 36 | printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __FUNCTION__ , ## arg); \ | 36 | printk(KERN_DEBUG __FILE__ ":%s(): " format "\n", __func__ , ## arg); \ |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | #else | 39 | #else |
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index bc4649a17b9d..183255fcfdcb 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c | |||
| @@ -242,6 +242,7 @@ static struct platform_driver physmap_flash_driver = { | |||
| 242 | .shutdown = physmap_flash_shutdown, | 242 | .shutdown = physmap_flash_shutdown, |
| 243 | .driver = { | 243 | .driver = { |
| 244 | .name = "physmap-flash", | 244 | .name = "physmap-flash", |
| 245 | .owner = THIS_MODULE, | ||
| 245 | }, | 246 | }, |
| 246 | }; | 247 | }; |
| 247 | 248 | ||
| @@ -319,3 +320,10 @@ module_exit(physmap_exit); | |||
| 319 | MODULE_LICENSE("GPL"); | 320 | MODULE_LICENSE("GPL"); |
| 320 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); | 321 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); |
| 321 | MODULE_DESCRIPTION("Generic configurable MTD map driver"); | 322 | MODULE_DESCRIPTION("Generic configurable MTD map driver"); |
| 323 | |||
| 324 | /* legacy platform drivers can't hotplug or coldplg */ | ||
| 325 | #ifndef PHYSMAP_COMPAT | ||
| 326 | /* work with hotplug and coldplug */ | ||
| 327 | MODULE_ALIAS("platform:physmap-flash"); | ||
| 328 | #endif | ||
| 329 | |||
diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c index 894c0b271289..f0b10ca05029 100644 --- a/drivers/mtd/maps/plat-ram.c +++ b/drivers/mtd/maps/plat-ram.c | |||
| @@ -47,6 +47,7 @@ struct platram_info { | |||
| 47 | struct mtd_info *mtd; | 47 | struct mtd_info *mtd; |
| 48 | struct map_info map; | 48 | struct map_info map; |
| 49 | struct mtd_partition *partitions; | 49 | struct mtd_partition *partitions; |
| 50 | bool free_partitions; | ||
| 50 | struct resource *area; | 51 | struct resource *area; |
| 51 | struct platdata_mtd_ram *pdata; | 52 | struct platdata_mtd_ram *pdata; |
| 52 | }; | 53 | }; |
| @@ -98,7 +99,8 @@ static int platram_remove(struct platform_device *pdev) | |||
| 98 | #ifdef CONFIG_MTD_PARTITIONS | 99 | #ifdef CONFIG_MTD_PARTITIONS |
| 99 | if (info->partitions) { | 100 | if (info->partitions) { |
| 100 | del_mtd_partitions(info->mtd); | 101 | del_mtd_partitions(info->mtd); |
| 101 | kfree(info->partitions); | 102 | if (info->free_partitions) |
| 103 | kfree(info->partitions); | ||
| 102 | } | 104 | } |
| 103 | #endif | 105 | #endif |
| 104 | del_mtd_device(info->mtd); | 106 | del_mtd_device(info->mtd); |
| @@ -176,7 +178,8 @@ static int platram_probe(struct platform_device *pdev) | |||
| 176 | 178 | ||
| 177 | info->map.phys = res->start; | 179 | info->map.phys = res->start; |
| 178 | info->map.size = (res->end - res->start) + 1; | 180 | info->map.size = (res->end - res->start) + 1; |
| 179 | info->map.name = pdata->mapname != NULL ? pdata->mapname : (char *)pdev->name; | 181 | info->map.name = pdata->mapname != NULL ? |
| 182 | (char *)pdata->mapname : (char *)pdev->name; | ||
| 180 | info->map.bankwidth = pdata->bankwidth; | 183 | info->map.bankwidth = pdata->bankwidth; |
| 181 | 184 | ||
| 182 | /* register our usage of the memory area */ | 185 | /* register our usage of the memory area */ |
| @@ -203,9 +206,19 @@ static int platram_probe(struct platform_device *pdev) | |||
| 203 | 206 | ||
| 204 | dev_dbg(&pdev->dev, "initialised map, probing for mtd\n"); | 207 | dev_dbg(&pdev->dev, "initialised map, probing for mtd\n"); |
| 205 | 208 | ||
| 206 | /* probe for the right mtd map driver */ | 209 | /* probe for the right mtd map driver |
| 210 | * supplied by the platform_data struct */ | ||
| 211 | |||
| 212 | if (pdata->map_probes != 0) { | ||
| 213 | const char **map_probes = pdata->map_probes; | ||
| 214 | |||
| 215 | for ( ; !info->mtd && *map_probes; map_probes++) | ||
| 216 | info->mtd = do_map_probe(*map_probes , &info->map); | ||
| 217 | } | ||
| 218 | /* fallback to map_ram */ | ||
| 219 | else | ||
| 220 | info->mtd = do_map_probe("map_ram", &info->map); | ||
| 207 | 221 | ||
| 208 | info->mtd = do_map_probe("map_ram" , &info->map); | ||
| 209 | if (info->mtd == NULL) { | 222 | if (info->mtd == NULL) { |
| 210 | dev_err(&pdev->dev, "failed to probe for map_ram\n"); | 223 | dev_err(&pdev->dev, "failed to probe for map_ram\n"); |
| 211 | err = -ENOMEM; | 224 | err = -ENOMEM; |
| @@ -220,19 +233,21 @@ static int platram_probe(struct platform_device *pdev) | |||
| 220 | * to add this device whole */ | 233 | * to add this device whole */ |
| 221 | 234 | ||
| 222 | #ifdef CONFIG_MTD_PARTITIONS | 235 | #ifdef CONFIG_MTD_PARTITIONS |
| 223 | if (pdata->nr_partitions > 0) { | 236 | if (!pdata->nr_partitions) { |
| 224 | const char **probes = { NULL }; | 237 | /* try to probe using the supplied probe type */ |
| 225 | 238 | if (pdata->probes) { | |
| 226 | if (pdata->probes) | 239 | err = parse_mtd_partitions(info->mtd, pdata->probes, |
| 227 | probes = (const char **)pdata->probes; | ||
| 228 | |||
| 229 | err = parse_mtd_partitions(info->mtd, probes, | ||
| 230 | &info->partitions, 0); | 240 | &info->partitions, 0); |
| 231 | if (err > 0) { | 241 | info->free_partitions = 1; |
| 232 | err = add_mtd_partitions(info->mtd, info->partitions, | 242 | if (err > 0) |
| 233 | err); | 243 | err = add_mtd_partitions(info->mtd, |
| 244 | info->partitions, err); | ||
| 234 | } | 245 | } |
| 235 | } | 246 | } |
| 247 | /* use the static mapping */ | ||
| 248 | else | ||
| 249 | err = add_mtd_partitions(info->mtd, pdata->partitions, | ||
| 250 | pdata->nr_partitions); | ||
| 236 | #endif /* CONFIG_MTD_PARTITIONS */ | 251 | #endif /* CONFIG_MTD_PARTITIONS */ |
| 237 | 252 | ||
| 238 | if (add_mtd_device(info->mtd)) { | 253 | if (add_mtd_device(info->mtd)) { |
| @@ -240,7 +255,9 @@ static int platram_probe(struct platform_device *pdev) | |||
| 240 | err = -ENOMEM; | 255 | err = -ENOMEM; |
| 241 | } | 256 | } |
| 242 | 257 | ||
| 243 | dev_info(&pdev->dev, "registered mtd device\n"); | 258 | if (!err) |
| 259 | dev_info(&pdev->dev, "registered mtd device\n"); | ||
| 260 | |||
| 244 | return err; | 261 | return err; |
| 245 | 262 | ||
| 246 | exit_free: | 263 | exit_free: |
| @@ -251,6 +268,9 @@ static int platram_probe(struct platform_device *pdev) | |||
| 251 | 268 | ||
| 252 | /* device driver info */ | 269 | /* device driver info */ |
| 253 | 270 | ||
| 271 | /* work with hotplug and coldplug */ | ||
| 272 | MODULE_ALIAS("platform:mtd-ram"); | ||
| 273 | |||
| 254 | static struct platform_driver platram_driver = { | 274 | static struct platform_driver platram_driver = { |
| 255 | .probe = platram_probe, | 275 | .probe = platram_probe, |
| 256 | .remove = platram_remove, | 276 | .remove = platram_remove, |
diff --git a/drivers/mtd/maps/pmcmsp-flash.c b/drivers/mtd/maps/pmcmsp-flash.c index 02bde8c982ec..f43ba2815cbb 100644 --- a/drivers/mtd/maps/pmcmsp-flash.c +++ b/drivers/mtd/maps/pmcmsp-flash.c | |||
| @@ -46,7 +46,7 @@ static struct mtd_partition **msp_parts; | |||
| 46 | static struct map_info *msp_maps; | 46 | static struct map_info *msp_maps; |
| 47 | static int fcnt; | 47 | static int fcnt; |
| 48 | 48 | ||
| 49 | #define DEBUG_MARKER printk(KERN_NOTICE "%s[%d]\n",__FUNCTION__,__LINE__) | 49 | #define DEBUG_MARKER printk(KERN_NOTICE "%s[%d]\n", __func__, __LINE__) |
| 50 | 50 | ||
| 51 | int __init init_msp_flash(void) | 51 | int __init init_msp_flash(void) |
| 52 | { | 52 | { |
diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index f904e6bd02e0..c7d5a52a2d55 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c | |||
| @@ -456,6 +456,7 @@ static struct platform_driver sa1100_mtd_driver = { | |||
| 456 | .shutdown = sa1100_mtd_shutdown, | 456 | .shutdown = sa1100_mtd_shutdown, |
| 457 | .driver = { | 457 | .driver = { |
| 458 | .name = "flash", | 458 | .name = "flash", |
| 459 | .owner = THIS_MODULE, | ||
| 459 | }, | 460 | }, |
| 460 | }; | 461 | }; |
| 461 | 462 | ||
| @@ -475,3 +476,4 @@ module_exit(sa1100_mtd_exit); | |||
| 475 | MODULE_AUTHOR("Nicolas Pitre"); | 476 | MODULE_AUTHOR("Nicolas Pitre"); |
| 476 | MODULE_DESCRIPTION("SA1100 CFI map driver"); | 477 | MODULE_DESCRIPTION("SA1100 CFI map driver"); |
| 477 | MODULE_LICENSE("GPL"); | 478 | MODULE_LICENSE("GPL"); |
| 479 | MODULE_ALIAS("platform:flash"); | ||
diff --git a/drivers/mtd/maps/sharpsl-flash.c b/drivers/mtd/maps/sharpsl-flash.c index 12fe53c0d2fc..917dc778f24e 100644 --- a/drivers/mtd/maps/sharpsl-flash.c +++ b/drivers/mtd/maps/sharpsl-flash.c | |||
| @@ -92,7 +92,7 @@ int __init init_sharpsl(void) | |||
| 92 | parts = sharpsl_partitions; | 92 | parts = sharpsl_partitions; |
| 93 | nb_parts = ARRAY_SIZE(sharpsl_partitions); | 93 | nb_parts = ARRAY_SIZE(sharpsl_partitions); |
| 94 | 94 | ||
| 95 | printk(KERN_NOTICE "Using %s partision definition\n", part_type); | 95 | printk(KERN_NOTICE "Using %s partition definition\n", part_type); |
| 96 | add_mtd_partitions(mymtd, parts, nb_parts); | 96 | add_mtd_partitions(mymtd, parts, nb_parts); |
| 97 | 97 | ||
| 98 | return 0; | 98 | return 0; |
diff --git a/drivers/mtd/maps/tqm8xxl.c b/drivers/mtd/maps/tqm8xxl.c index 37e4ded9b600..521734057314 100644 --- a/drivers/mtd/maps/tqm8xxl.c +++ b/drivers/mtd/maps/tqm8xxl.c | |||
| @@ -124,7 +124,7 @@ int __init init_tqm_mtd(void) | |||
| 124 | //request maximum flash size address space | 124 | //request maximum flash size address space |
| 125 | start_scan_addr = ioremap(flash_addr, flash_size); | 125 | start_scan_addr = ioremap(flash_addr, flash_size); |
| 126 | if (!start_scan_addr) { | 126 | if (!start_scan_addr) { |
| 127 | printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __FUNCTION__, flash_addr); | 127 | printk(KERN_WARNING "%s:Failed to ioremap address:0x%x\n", __func__, flash_addr); |
| 128 | return -EIO; | 128 | return -EIO; |
| 129 | } | 129 | } |
| 130 | 130 | ||
| @@ -132,7 +132,7 @@ int __init init_tqm_mtd(void) | |||
| 132 | if(mtd_size >= flash_size) | 132 | if(mtd_size >= flash_size) |
| 133 | break; | 133 | break; |
| 134 | 134 | ||
| 135 | printk(KERN_INFO "%s: chip probing count %d\n", __FUNCTION__, idx); | 135 | printk(KERN_INFO "%s: chip probing count %d\n", __func__, idx); |
| 136 | 136 | ||
| 137 | map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL); | 137 | map_banks[idx] = kzalloc(sizeof(struct map_info), GFP_KERNEL); |
| 138 | if(map_banks[idx] == NULL) { | 138 | if(map_banks[idx] == NULL) { |
| @@ -178,7 +178,7 @@ int __init init_tqm_mtd(void) | |||
| 178 | mtd_size += mtd_banks[idx]->size; | 178 | mtd_size += mtd_banks[idx]->size; |
| 179 | num_banks++; | 179 | num_banks++; |
| 180 | 180 | ||
| 181 | printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __FUNCTION__, num_banks, | 181 | printk(KERN_INFO "%s: bank%d, name:%s, size:%dbytes \n", __func__, num_banks, |
| 182 | mtd_banks[idx]->name, mtd_banks[idx]->size); | 182 | mtd_banks[idx]->name, mtd_banks[idx]->size); |
| 183 | } | 183 | } |
| 184 | } | 184 | } |
diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c index d3cf05012b46..5a680e1e61f1 100644 --- a/drivers/mtd/mtdoops.c +++ b/drivers/mtd/mtdoops.c | |||
| @@ -35,7 +35,7 @@ | |||
| 35 | 35 | ||
| 36 | #define OOPS_PAGE_SIZE 4096 | 36 | #define OOPS_PAGE_SIZE 4096 |
| 37 | 37 | ||
| 38 | struct mtdoops_context { | 38 | static struct mtdoops_context { |
| 39 | int mtd_index; | 39 | int mtd_index; |
| 40 | struct work_struct work_erase; | 40 | struct work_struct work_erase; |
| 41 | struct work_struct work_write; | 41 | struct work_struct work_write; |
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 959fb86cda01..5076faf9ca66 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig | |||
| @@ -278,6 +278,54 @@ config MTD_NAND_AT91 | |||
| 278 | help | 278 | help |
| 279 | Enables support for NAND Flash / Smart Media Card interface | 279 | Enables support for NAND Flash / Smart Media Card interface |
| 280 | on Atmel AT91 processors. | 280 | on Atmel AT91 processors. |
| 281 | choice | ||
| 282 | prompt "ECC management for NAND Flash / SmartMedia on AT91" | ||
| 283 | depends on MTD_NAND_AT91 | ||
| 284 | |||
| 285 | config MTD_NAND_AT91_ECC_HW | ||
| 286 | bool "Hardware ECC" | ||
| 287 | depends on ARCH_AT91SAM9263 || ARCH_AT91SAM9260 | ||
| 288 | help | ||
| 289 | Uses hardware ECC provided by the at91sam9260/at91sam9263 chip | ||
| 290 | instead of software ECC. | ||
| 291 | The hardware ECC controller is capable of single bit error | ||
| 292 | correction and 2-bit random detection per page. | ||
| 293 | |||
| 294 | NB : hardware and software ECC schemes are incompatible. | ||
| 295 | If you switch from one to another, you'll have to erase your | ||
| 296 | mtd partition. | ||
| 297 | |||
| 298 | If unsure, say Y | ||
| 299 | |||
| 300 | config MTD_NAND_AT91_ECC_SOFT | ||
| 301 | bool "Software ECC" | ||
| 302 | help | ||
| 303 | Uses software ECC. | ||
| 304 | |||
| 305 | NB : hardware and software ECC schemes are incompatible. | ||
| 306 | If you switch from one to another, you'll have to erase your | ||
| 307 | mtd partition. | ||
| 308 | |||
| 309 | config MTD_NAND_AT91_ECC_NONE | ||
| 310 | bool "No ECC (testing only, DANGEROUS)" | ||
| 311 | depends on DEBUG_KERNEL | ||
| 312 | help | ||
| 313 | No ECC will be used. | ||
| 314 | It's not a good idea and it should be reserved for testing | ||
| 315 | purpose only. | ||
| 316 | |||
| 317 | If unsure, say N | ||
| 318 | |||
| 319 | endchoice | ||
| 320 | |||
| 321 | endchoice | ||
| 322 | |||
| 323 | config MTD_NAND_PXA3xx | ||
| 324 | bool "Support for NAND flash devices on PXA3xx" | ||
| 325 | depends on MTD_NAND && PXA3xx | ||
| 326 | help | ||
| 327 | This enables the driver for the NAND flash device found on | ||
| 328 | PXA3xx processors | ||
| 281 | 329 | ||
| 282 | config MTD_NAND_CM_X270 | 330 | config MTD_NAND_CM_X270 |
| 283 | tristate "Support for NAND Flash on CM-X270 modules" | 331 | tristate "Support for NAND Flash on CM-X270 modules" |
| @@ -330,4 +378,12 @@ config MTD_NAND_FSL_ELBC | |||
| 330 | Enabling this option will enable you to use this to control | 378 | Enabling this option will enable you to use this to control |
| 331 | external NAND devices. | 379 | external NAND devices. |
| 332 | 380 | ||
| 381 | config MTD_NAND_FSL_UPM | ||
| 382 | tristate "Support for NAND on Freescale UPM" | ||
| 383 | depends on MTD_NAND && OF_GPIO && (PPC_83xx || PPC_85xx) | ||
| 384 | select FSL_LBC | ||
| 385 | help | ||
| 386 | Enables support for NAND Flash chips wired onto Freescale PowerPC | ||
| 387 | processor localbus with User-Programmable Machine support. | ||
| 388 | |||
| 333 | endif # MTD_NAND | 389 | endif # MTD_NAND |
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile index 80d575eeee96..a6e74a46992a 100644 --- a/drivers/mtd/nand/Makefile +++ b/drivers/mtd/nand/Makefile | |||
| @@ -27,10 +27,12 @@ obj-$(CONFIG_MTD_NAND_NDFC) += ndfc.o | |||
| 27 | obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o | 27 | obj-$(CONFIG_MTD_NAND_AT91) += at91_nand.o |
| 28 | obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o | 28 | obj-$(CONFIG_MTD_NAND_CM_X270) += cmx270_nand.o |
| 29 | obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o | 29 | obj-$(CONFIG_MTD_NAND_BASLER_EXCITE) += excite_nandflash.o |
| 30 | obj-$(CONFIG_MTD_NAND_PXA3xx) += pxa3xx_nand.o | ||
| 30 | obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o | 31 | obj-$(CONFIG_MTD_NAND_PLATFORM) += plat_nand.o |
| 31 | obj-$(CONFIG_MTD_ALAUDA) += alauda.o | 32 | obj-$(CONFIG_MTD_ALAUDA) += alauda.o |
| 32 | obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o | 33 | obj-$(CONFIG_MTD_NAND_PASEMI) += pasemi_nand.o |
| 33 | obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o | 34 | obj-$(CONFIG_MTD_NAND_ORION) += orion_nand.o |
| 34 | obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o | 35 | obj-$(CONFIG_MTD_NAND_FSL_ELBC) += fsl_elbc_nand.o |
| 36 | obj-$(CONFIG_MTD_NAND_FSL_UPM) += fsl_upm.o | ||
| 35 | 37 | ||
| 36 | nand-objs := nand_base.o nand_bbt.o | 38 | nand-objs := nand_base.o nand_bbt.o |
diff --git a/drivers/mtd/nand/at91_nand.c b/drivers/mtd/nand/at91_nand.c index c9fb2acf4056..414ceaecdb3a 100644 --- a/drivers/mtd/nand/at91_nand.c +++ b/drivers/mtd/nand/at91_nand.c | |||
| @@ -9,6 +9,15 @@ | |||
| 9 | * Derived from drivers/mtd/spia.c | 9 | * Derived from drivers/mtd/spia.c |
| 10 | * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) | 10 | * Copyright (C) 2000 Steven J. Hill (sjhill@cotw.com) |
| 11 | * | 11 | * |
| 12 | * | ||
| 13 | * Add Hardware ECC support for AT91SAM9260 / AT91SAM9263 | ||
| 14 | * Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright (C) 2007 | ||
| 15 | * | ||
| 16 | * Derived from Das U-Boot source code | ||
| 17 | * (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c) | ||
| 18 | * (C) Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas | ||
| 19 | * | ||
| 20 | * | ||
| 12 | * This program is free software; you can redistribute it and/or modify | 21 | * This program is free software; you can redistribute it and/or modify |
| 13 | * it under the terms of the GNU General Public License version 2 as | 22 | * it under the terms of the GNU General Public License version 2 as |
| 14 | * published by the Free Software Foundation. | 23 | * published by the Free Software Foundation. |
| @@ -29,11 +38,59 @@ | |||
| 29 | #include <asm/arch/board.h> | 38 | #include <asm/arch/board.h> |
| 30 | #include <asm/arch/gpio.h> | 39 | #include <asm/arch/gpio.h> |
| 31 | 40 | ||
| 41 | #ifdef CONFIG_MTD_NAND_AT91_ECC_HW | ||
| 42 | #define hard_ecc 1 | ||
| 43 | #else | ||
| 44 | #define hard_ecc 0 | ||
| 45 | #endif | ||
| 46 | |||
| 47 | #ifdef CONFIG_MTD_NAND_AT91_ECC_NONE | ||
| 48 | #define no_ecc 1 | ||
| 49 | #else | ||
| 50 | #define no_ecc 0 | ||
| 51 | #endif | ||
| 52 | |||
| 53 | /* Register access macros */ | ||
| 54 | #define ecc_readl(add, reg) \ | ||
| 55 | __raw_readl(add + AT91_ECC_##reg) | ||
| 56 | #define ecc_writel(add, reg, value) \ | ||
| 57 | __raw_writel((value), add + AT91_ECC_##reg) | ||
| 58 | |||
| 59 | #include <asm/arch/at91_ecc.h> /* AT91SAM9260/3 ECC registers */ | ||
| 60 | |||
| 61 | /* oob layout for large page size | ||
| 62 | * bad block info is on bytes 0 and 1 | ||
| 63 | * the bytes have to be consecutives to avoid | ||
| 64 | * several NAND_CMD_RNDOUT during read | ||
| 65 | */ | ||
| 66 | static struct nand_ecclayout at91_oobinfo_large = { | ||
| 67 | .eccbytes = 4, | ||
| 68 | .eccpos = {60, 61, 62, 63}, | ||
| 69 | .oobfree = { | ||
| 70 | {2, 58} | ||
| 71 | }, | ||
| 72 | }; | ||
| 73 | |||
| 74 | /* oob layout for small page size | ||
| 75 | * bad block info is on bytes 4 and 5 | ||
| 76 | * the bytes have to be consecutives to avoid | ||
| 77 | * several NAND_CMD_RNDOUT during read | ||
| 78 | */ | ||
| 79 | static struct nand_ecclayout at91_oobinfo_small = { | ||
| 80 | .eccbytes = 4, | ||
| 81 | .eccpos = {0, 1, 2, 3}, | ||
| 82 | .oobfree = { | ||
| 83 | {6, 10} | ||
| 84 | }, | ||
| 85 | }; | ||
| 86 | |||
| 32 | struct at91_nand_host { | 87 | struct at91_nand_host { |
| 33 | struct nand_chip nand_chip; | 88 | struct nand_chip nand_chip; |
| 34 | struct mtd_info mtd; | 89 | struct mtd_info mtd; |
| 35 | void __iomem *io_base; | 90 | void __iomem *io_base; |
| 36 | struct at91_nand_data *board; | 91 | struct at91_nand_data *board; |
| 92 | struct device *dev; | ||
| 93 | void __iomem *ecc; | ||
| 37 | }; | 94 | }; |
| 38 | 95 | ||
| 39 | /* | 96 | /* |
| @@ -44,6 +101,12 @@ static void at91_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | |||
| 44 | struct nand_chip *nand_chip = mtd->priv; | 101 | struct nand_chip *nand_chip = mtd->priv; |
| 45 | struct at91_nand_host *host = nand_chip->priv; | 102 | struct at91_nand_host *host = nand_chip->priv; |
| 46 | 103 | ||
| 104 | if (host->board->enable_pin && (ctrl & NAND_CTRL_CHANGE)) { | ||
| 105 | if (ctrl & NAND_NCE) | ||
| 106 | at91_set_gpio_value(host->board->enable_pin, 0); | ||
| 107 | else | ||
| 108 | at91_set_gpio_value(host->board->enable_pin, 1); | ||
| 109 | } | ||
| 47 | if (cmd == NAND_CMD_NONE) | 110 | if (cmd == NAND_CMD_NONE) |
| 48 | return; | 111 | return; |
| 49 | 112 | ||
| @@ -82,8 +145,217 @@ static void at91_nand_disable(struct at91_nand_host *host) | |||
| 82 | at91_set_gpio_value(host->board->enable_pin, 1); | 145 | at91_set_gpio_value(host->board->enable_pin, 1); |
| 83 | } | 146 | } |
| 84 | 147 | ||
| 148 | /* | ||
| 149 | * write oob for small pages | ||
| 150 | */ | ||
| 151 | static int at91_nand_write_oob_512(struct mtd_info *mtd, | ||
| 152 | struct nand_chip *chip, int page) | ||
| 153 | { | ||
| 154 | int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad; | ||
| 155 | int eccsize = chip->ecc.size, length = mtd->oobsize; | ||
| 156 | int len, pos, status = 0; | ||
| 157 | const uint8_t *bufpoi = chip->oob_poi; | ||
| 158 | |||
| 159 | pos = eccsize + chunk; | ||
| 160 | |||
| 161 | chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page); | ||
| 162 | len = min_t(int, length, chunk); | ||
| 163 | chip->write_buf(mtd, bufpoi, len); | ||
| 164 | bufpoi += len; | ||
| 165 | length -= len; | ||
| 166 | if (length > 0) | ||
| 167 | chip->write_buf(mtd, bufpoi, length); | ||
| 168 | |||
| 169 | chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1); | ||
| 170 | status = chip->waitfunc(mtd, chip); | ||
| 171 | |||
| 172 | return status & NAND_STATUS_FAIL ? -EIO : 0; | ||
| 173 | |||
| 174 | } | ||
| 175 | |||
| 176 | /* | ||
| 177 | * read oob for small pages | ||
| 178 | */ | ||
| 179 | static int at91_nand_read_oob_512(struct mtd_info *mtd, | ||
| 180 | struct nand_chip *chip, int page, int sndcmd) | ||
| 181 | { | ||
| 182 | if (sndcmd) { | ||
| 183 | chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); | ||
| 184 | sndcmd = 0; | ||
| 185 | } | ||
| 186 | chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); | ||
| 187 | return sndcmd; | ||
| 188 | } | ||
| 189 | |||
| 190 | /* | ||
| 191 | * Calculate HW ECC | ||
| 192 | * | ||
| 193 | * function called after a write | ||
| 194 | * | ||
| 195 | * mtd: MTD block structure | ||
| 196 | * dat: raw data (unused) | ||
| 197 | * ecc_code: buffer for ECC | ||
| 198 | */ | ||
| 199 | static int at91_nand_calculate(struct mtd_info *mtd, | ||
| 200 | const u_char *dat, unsigned char *ecc_code) | ||
| 201 | { | ||
| 202 | struct nand_chip *nand_chip = mtd->priv; | ||
| 203 | struct at91_nand_host *host = nand_chip->priv; | ||
| 204 | uint32_t *eccpos = nand_chip->ecc.layout->eccpos; | ||
| 205 | unsigned int ecc_value; | ||
| 206 | |||
| 207 | /* get the first 2 ECC bytes */ | ||
| 208 | ecc_value = ecc_readl(host->ecc, PR); | ||
| 209 | |||
| 210 | ecc_code[eccpos[0]] = ecc_value & 0xFF; | ||
| 211 | ecc_code[eccpos[1]] = (ecc_value >> 8) & 0xFF; | ||
| 212 | |||
| 213 | /* get the last 2 ECC bytes */ | ||
| 214 | ecc_value = ecc_readl(host->ecc, NPR) & AT91_ECC_NPARITY; | ||
| 215 | |||
| 216 | ecc_code[eccpos[2]] = ecc_value & 0xFF; | ||
| 217 | ecc_code[eccpos[3]] = (ecc_value >> 8) & 0xFF; | ||
| 218 | |||
| 219 | return 0; | ||
| 220 | } | ||
| 221 | |||
| 222 | /* | ||
| 223 | * HW ECC read page function | ||
| 224 | * | ||
| 225 | * mtd: mtd info structure | ||
| 226 | * chip: nand chip info structure | ||
| 227 | * buf: buffer to store read data | ||
| 228 | */ | ||
| 229 | static int at91_nand_read_page(struct mtd_info *mtd, | ||
| 230 | struct nand_chip *chip, uint8_t *buf) | ||
| 231 | { | ||
| 232 | int eccsize = chip->ecc.size; | ||
| 233 | int eccbytes = chip->ecc.bytes; | ||
| 234 | uint32_t *eccpos = chip->ecc.layout->eccpos; | ||
| 235 | uint8_t *p = buf; | ||
| 236 | uint8_t *oob = chip->oob_poi; | ||
| 237 | uint8_t *ecc_pos; | ||
| 238 | int stat; | ||
| 239 | |||
| 240 | /* read the page */ | ||
| 241 | chip->read_buf(mtd, p, eccsize); | ||
| 242 | |||
| 243 | /* move to ECC position if needed */ | ||
| 244 | if (eccpos[0] != 0) { | ||
| 245 | /* This only works on large pages | ||
| 246 | * because the ECC controller waits for | ||
| 247 | * NAND_CMD_RNDOUTSTART after the | ||
| 248 | * NAND_CMD_RNDOUT. | ||
| 249 | * anyway, for small pages, the eccpos[0] == 0 | ||
| 250 | */ | ||
| 251 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, | ||
| 252 | mtd->writesize + eccpos[0], -1); | ||
| 253 | } | ||
| 254 | |||
| 255 | /* the ECC controller needs to read the ECC just after the data */ | ||
| 256 | ecc_pos = oob + eccpos[0]; | ||
| 257 | chip->read_buf(mtd, ecc_pos, eccbytes); | ||
| 258 | |||
| 259 | /* check if there's an error */ | ||
| 260 | stat = chip->ecc.correct(mtd, p, oob, NULL); | ||
| 261 | |||
| 262 | if (stat < 0) | ||
| 263 | mtd->ecc_stats.failed++; | ||
| 264 | else | ||
| 265 | mtd->ecc_stats.corrected += stat; | ||
| 266 | |||
| 267 | /* get back to oob start (end of page) */ | ||
| 268 | chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1); | ||
| 269 | |||
| 270 | /* read the oob */ | ||
| 271 | chip->read_buf(mtd, oob, mtd->oobsize); | ||
| 272 | |||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | /* | ||
| 277 | * HW ECC Correction | ||
| 278 | * | ||
| 279 | * function called after a read | ||
| 280 | * | ||
| 281 | * mtd: MTD block structure | ||
| 282 | * dat: raw data read from the chip | ||
| 283 | * read_ecc: ECC from the chip (unused) | ||
| 284 | * isnull: unused | ||
| 285 | * | ||
| 286 | * Detect and correct a 1 bit error for a page | ||
| 287 | */ | ||
| 288 | static int at91_nand_correct(struct mtd_info *mtd, u_char *dat, | ||
| 289 | u_char *read_ecc, u_char *isnull) | ||
| 290 | { | ||
| 291 | struct nand_chip *nand_chip = mtd->priv; | ||
| 292 | struct at91_nand_host *host = nand_chip->priv; | ||
| 293 | unsigned int ecc_status; | ||
| 294 | unsigned int ecc_word, ecc_bit; | ||
| 295 | |||
| 296 | /* get the status from the Status Register */ | ||
| 297 | ecc_status = ecc_readl(host->ecc, SR); | ||
| 298 | |||
| 299 | /* if there's no error */ | ||
| 300 | if (likely(!(ecc_status & AT91_ECC_RECERR))) | ||
| 301 | return 0; | ||
| 302 | |||
| 303 | /* get error bit offset (4 bits) */ | ||
| 304 | ecc_bit = ecc_readl(host->ecc, PR) & AT91_ECC_BITADDR; | ||
| 305 | /* get word address (12 bits) */ | ||
| 306 | ecc_word = ecc_readl(host->ecc, PR) & AT91_ECC_WORDADDR; | ||
| 307 | ecc_word >>= 4; | ||
| 308 | |||
| 309 | /* if there are multiple errors */ | ||
| 310 | if (ecc_status & AT91_ECC_MULERR) { | ||
| 311 | /* check if it is a freshly erased block | ||
| 312 | * (filled with 0xff) */ | ||
| 313 | if ((ecc_bit == AT91_ECC_BITADDR) | ||
| 314 | && (ecc_word == (AT91_ECC_WORDADDR >> 4))) { | ||
| 315 | /* the block has just been erased, return OK */ | ||
| 316 | return 0; | ||
| 317 | } | ||
| 318 | /* it doesn't seems to be a freshly | ||
| 319 | * erased block. | ||
| 320 | * We can't correct so many errors */ | ||
| 321 | dev_dbg(host->dev, "at91_nand : multiple errors detected." | ||
| 322 | " Unable to correct.\n"); | ||
| 323 | return -EIO; | ||
| 324 | } | ||
| 325 | |||
| 326 | /* if there's a single bit error : we can correct it */ | ||
| 327 | if (ecc_status & AT91_ECC_ECCERR) { | ||
| 328 | /* there's nothing much to do here. | ||
| 329 | * the bit error is on the ECC itself. | ||
| 330 | */ | ||
| 331 | dev_dbg(host->dev, "at91_nand : one bit error on ECC code." | ||
| 332 | " Nothing to correct\n"); | ||
| 333 | return 0; | ||
| 334 | } | ||
| 335 | |||
| 336 | dev_dbg(host->dev, "at91_nand : one bit error on data." | ||
| 337 | " (word offset in the page :" | ||
| 338 | " 0x%x bit offset : 0x%x)\n", | ||
| 339 | ecc_word, ecc_bit); | ||
| 340 | /* correct the error */ | ||
| 341 | if (nand_chip->options & NAND_BUSWIDTH_16) { | ||
| 342 | /* 16 bits words */ | ||
| 343 | ((unsigned short *) dat)[ecc_word] ^= (1 << ecc_bit); | ||
| 344 | } else { | ||
| 345 | /* 8 bits words */ | ||
| 346 | dat[ecc_word] ^= (1 << ecc_bit); | ||
| 347 | } | ||
| 348 | dev_dbg(host->dev, "at91_nand : error corrected\n"); | ||
| 349 | return 1; | ||
| 350 | } | ||
| 351 | |||
| 352 | /* | ||
| 353 | * Enable HW ECC : unsused | ||
| 354 | */ | ||
| 355 | static void at91_nand_hwctl(struct mtd_info *mtd, int mode) { ; } | ||
| 356 | |||
| 85 | #ifdef CONFIG_MTD_PARTITIONS | 357 | #ifdef CONFIG_MTD_PARTITIONS |
| 86 | const char *part_probes[] = { "cmdlinepart", NULL }; | 358 | static const char *part_probes[] = { "cmdlinepart", NULL }; |
| 87 | #endif | 359 | #endif |
| 88 | 360 | ||
| 89 | /* | 361 | /* |
| @@ -94,6 +366,8 @@ static int __init at91_nand_probe(struct platform_device *pdev) | |||
| 94 | struct at91_nand_host *host; | 366 | struct at91_nand_host *host; |
| 95 | struct mtd_info *mtd; | 367 | struct mtd_info *mtd; |
| 96 | struct nand_chip *nand_chip; | 368 | struct nand_chip *nand_chip; |
| 369 | struct resource *regs; | ||
| 370 | struct resource *mem; | ||
| 97 | int res; | 371 | int res; |
| 98 | 372 | ||
| 99 | #ifdef CONFIG_MTD_PARTITIONS | 373 | #ifdef CONFIG_MTD_PARTITIONS |
| @@ -108,8 +382,13 @@ static int __init at91_nand_probe(struct platform_device *pdev) | |||
| 108 | return -ENOMEM; | 382 | return -ENOMEM; |
| 109 | } | 383 | } |
| 110 | 384 | ||
| 111 | host->io_base = ioremap(pdev->resource[0].start, | 385 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 112 | pdev->resource[0].end - pdev->resource[0].start + 1); | 386 | if (!mem) { |
| 387 | printk(KERN_ERR "at91_nand: can't get I/O resource mem\n"); | ||
| 388 | return -ENXIO; | ||
| 389 | } | ||
| 390 | |||
| 391 | host->io_base = ioremap(mem->start, mem->end - mem->start + 1); | ||
| 113 | if (host->io_base == NULL) { | 392 | if (host->io_base == NULL) { |
| 114 | printk(KERN_ERR "at91_nand: ioremap failed\n"); | 393 | printk(KERN_ERR "at91_nand: ioremap failed\n"); |
| 115 | kfree(host); | 394 | kfree(host); |
| @@ -119,6 +398,7 @@ static int __init at91_nand_probe(struct platform_device *pdev) | |||
| 119 | mtd = &host->mtd; | 398 | mtd = &host->mtd; |
| 120 | nand_chip = &host->nand_chip; | 399 | nand_chip = &host->nand_chip; |
| 121 | host->board = pdev->dev.platform_data; | 400 | host->board = pdev->dev.platform_data; |
| 401 | host->dev = &pdev->dev; | ||
| 122 | 402 | ||
| 123 | nand_chip->priv = host; /* link the private data structures */ | 403 | nand_chip->priv = host; /* link the private data structures */ |
| 124 | mtd->priv = nand_chip; | 404 | mtd->priv = nand_chip; |
| @@ -132,7 +412,32 @@ static int __init at91_nand_probe(struct platform_device *pdev) | |||
| 132 | if (host->board->rdy_pin) | 412 | if (host->board->rdy_pin) |
| 133 | nand_chip->dev_ready = at91_nand_device_ready; | 413 | nand_chip->dev_ready = at91_nand_device_ready; |
| 134 | 414 | ||
| 415 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 1); | ||
| 416 | if (!regs && hard_ecc) { | ||
| 417 | printk(KERN_ERR "at91_nand: can't get I/O resource " | ||
| 418 | "regs\nFalling back on software ECC\n"); | ||
| 419 | } | ||
| 420 | |||
| 135 | nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */ | 421 | nand_chip->ecc.mode = NAND_ECC_SOFT; /* enable ECC */ |
| 422 | if (no_ecc) | ||
| 423 | nand_chip->ecc.mode = NAND_ECC_NONE; | ||
| 424 | if (hard_ecc && regs) { | ||
| 425 | host->ecc = ioremap(regs->start, regs->end - regs->start + 1); | ||
| 426 | if (host->ecc == NULL) { | ||
| 427 | printk(KERN_ERR "at91_nand: ioremap failed\n"); | ||
| 428 | res = -EIO; | ||
| 429 | goto err_ecc_ioremap; | ||
| 430 | } | ||
| 431 | nand_chip->ecc.mode = NAND_ECC_HW_SYNDROME; | ||
| 432 | nand_chip->ecc.calculate = at91_nand_calculate; | ||
| 433 | nand_chip->ecc.correct = at91_nand_correct; | ||
| 434 | nand_chip->ecc.hwctl = at91_nand_hwctl; | ||
| 435 | nand_chip->ecc.read_page = at91_nand_read_page; | ||
| 436 | nand_chip->ecc.bytes = 4; | ||
| 437 | nand_chip->ecc.prepad = 0; | ||
| 438 | nand_chip->ecc.postpad = 0; | ||
| 439 | } | ||
| 440 | |||
| 136 | nand_chip->chip_delay = 20; /* 20us command delay time */ | 441 | nand_chip->chip_delay = 20; /* 20us command delay time */ |
| 137 | 442 | ||
| 138 | if (host->board->bus_width_16) /* 16-bit bus width */ | 443 | if (host->board->bus_width_16) /* 16-bit bus width */ |
| @@ -149,8 +454,53 @@ static int __init at91_nand_probe(struct platform_device *pdev) | |||
| 149 | } | 454 | } |
| 150 | } | 455 | } |
| 151 | 456 | ||
| 152 | /* Scan to find existance of the device */ | 457 | /* first scan to find the device and get the page size */ |
| 153 | if (nand_scan(mtd, 1)) { | 458 | if (nand_scan_ident(mtd, 1)) { |
| 459 | res = -ENXIO; | ||
| 460 | goto out; | ||
| 461 | } | ||
| 462 | |||
| 463 | if (nand_chip->ecc.mode == NAND_ECC_HW_SYNDROME) { | ||
| 464 | /* ECC is calculated for the whole page (1 step) */ | ||
| 465 | nand_chip->ecc.size = mtd->writesize; | ||
| 466 | |||
| 467 | /* set ECC page size and oob layout */ | ||
| 468 | switch (mtd->writesize) { | ||
| 469 | case 512: | ||
| 470 | nand_chip->ecc.layout = &at91_oobinfo_small; | ||
| 471 | nand_chip->ecc.read_oob = at91_nand_read_oob_512; | ||
| 472 | nand_chip->ecc.write_oob = at91_nand_write_oob_512; | ||
| 473 | ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_528); | ||
| 474 | break; | ||
| 475 | case 1024: | ||
| 476 | nand_chip->ecc.layout = &at91_oobinfo_large; | ||
| 477 | ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_1056); | ||
| 478 | break; | ||
| 479 | case 2048: | ||
| 480 | nand_chip->ecc.layout = &at91_oobinfo_large; | ||
| 481 | ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_2112); | ||
| 482 | break; | ||
| 483 | case 4096: | ||
| 484 | nand_chip->ecc.layout = &at91_oobinfo_large; | ||
| 485 | ecc_writel(host->ecc, MR, AT91_ECC_PAGESIZE_4224); | ||
| 486 | break; | ||
| 487 | default: | ||
| 488 | /* page size not handled by HW ECC */ | ||
| 489 | /* switching back to soft ECC */ | ||
| 490 | nand_chip->ecc.mode = NAND_ECC_SOFT; | ||
| 491 | nand_chip->ecc.calculate = NULL; | ||
| 492 | nand_chip->ecc.correct = NULL; | ||
| 493 | nand_chip->ecc.hwctl = NULL; | ||
| 494 | nand_chip->ecc.read_page = NULL; | ||
| 495 | nand_chip->ecc.postpad = 0; | ||
| 496 | nand_chip->ecc.prepad = 0; | ||
| 497 | nand_chip->ecc.bytes = 0; | ||
| 498 | break; | ||
| 499 | } | ||
| 500 | } | ||
| 501 | |||
| 502 | /* second phase scan */ | ||
| 503 | if (nand_scan_tail(mtd)) { | ||
| 154 | res = -ENXIO; | 504 | res = -ENXIO; |
| 155 | goto out; | 505 | goto out; |
| 156 | } | 506 | } |
| @@ -179,9 +529,15 @@ static int __init at91_nand_probe(struct platform_device *pdev) | |||
| 179 | if (!res) | 529 | if (!res) |
| 180 | return res; | 530 | return res; |
| 181 | 531 | ||
| 532 | #ifdef CONFIG_MTD_PARTITIONS | ||
| 182 | release: | 533 | release: |
| 534 | #endif | ||
| 183 | nand_release(mtd); | 535 | nand_release(mtd); |
| 536 | |||
| 184 | out: | 537 | out: |
| 538 | iounmap(host->ecc); | ||
| 539 | |||
| 540 | err_ecc_ioremap: | ||
| 185 | at91_nand_disable(host); | 541 | at91_nand_disable(host); |
| 186 | platform_set_drvdata(pdev, NULL); | 542 | platform_set_drvdata(pdev, NULL); |
| 187 | iounmap(host->io_base); | 543 | iounmap(host->io_base); |
| @@ -202,6 +558,7 @@ static int __devexit at91_nand_remove(struct platform_device *pdev) | |||
| 202 | at91_nand_disable(host); | 558 | at91_nand_disable(host); |
| 203 | 559 | ||
| 204 | iounmap(host->io_base); | 560 | iounmap(host->io_base); |
| 561 | iounmap(host->ecc); | ||
| 205 | kfree(host); | 562 | kfree(host); |
| 206 | 563 | ||
| 207 | return 0; | 564 | return 0; |
| @@ -233,4 +590,5 @@ module_exit(at91_nand_exit); | |||
| 233 | 590 | ||
| 234 | MODULE_LICENSE("GPL"); | 591 | MODULE_LICENSE("GPL"); |
| 235 | MODULE_AUTHOR("Rick Bronson"); | 592 | MODULE_AUTHOR("Rick Bronson"); |
| 236 | MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200"); | 593 | MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91RM9200 / AT91SAM9"); |
| 594 | MODULE_ALIAS("platform:at91_nand"); | ||
diff --git a/drivers/mtd/nand/bf5xx_nand.c b/drivers/mtd/nand/bf5xx_nand.c index 747042ab094a..e87a57297328 100644 --- a/drivers/mtd/nand/bf5xx_nand.c +++ b/drivers/mtd/nand/bf5xx_nand.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* linux/drivers/mtd/nand/bf5xx_nand.c | 1 | /* linux/drivers/mtd/nand/bf5xx_nand.c |
| 2 | * | 2 | * |
| 3 | * Copyright 2006-2007 Analog Devices Inc. | 3 | * Copyright 2006-2008 Analog Devices Inc. |
| 4 | * http://blackfin.uclinux.org/ | 4 | * http://blackfin.uclinux.org/ |
| 5 | * Bryan Wu <bryan.wu@analog.com> | 5 | * Bryan Wu <bryan.wu@analog.com> |
| 6 | * | 6 | * |
| @@ -74,7 +74,7 @@ static int hardware_ecc = 1; | |||
| 74 | static int hardware_ecc; | 74 | static int hardware_ecc; |
| 75 | #endif | 75 | #endif |
| 76 | 76 | ||
| 77 | static unsigned short bfin_nfc_pin_req[] = | 77 | static const unsigned short bfin_nfc_pin_req[] = |
| 78 | {P_NAND_CE, | 78 | {P_NAND_CE, |
| 79 | P_NAND_RB, | 79 | P_NAND_RB, |
| 80 | P_NAND_D0, | 80 | P_NAND_D0, |
| @@ -581,12 +581,6 @@ static int bf5xx_nand_hw_init(struct bf5xx_nand_info *info) | |||
| 581 | bfin_write_NFC_IRQSTAT(val); | 581 | bfin_write_NFC_IRQSTAT(val); |
| 582 | SSYNC(); | 582 | SSYNC(); |
| 583 | 583 | ||
| 584 | if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) { | ||
| 585 | printk(KERN_ERR DRV_NAME | ||
| 586 | ": Requesting Peripherals failed\n"); | ||
| 587 | return -EFAULT; | ||
| 588 | } | ||
| 589 | |||
| 590 | /* DMA initialization */ | 584 | /* DMA initialization */ |
| 591 | if (bf5xx_nand_dma_init(info)) | 585 | if (bf5xx_nand_dma_init(info)) |
| 592 | err = -ENXIO; | 586 | err = -ENXIO; |
| @@ -654,6 +648,12 @@ static int bf5xx_nand_probe(struct platform_device *pdev) | |||
| 654 | 648 | ||
| 655 | dev_dbg(&pdev->dev, "(%p)\n", pdev); | 649 | dev_dbg(&pdev->dev, "(%p)\n", pdev); |
| 656 | 650 | ||
| 651 | if (peripheral_request_list(bfin_nfc_pin_req, DRV_NAME)) { | ||
| 652 | printk(KERN_ERR DRV_NAME | ||
| 653 | ": Requesting Peripherals failed\n"); | ||
| 654 | return -EFAULT; | ||
| 655 | } | ||
| 656 | |||
| 657 | if (!plat) { | 657 | if (!plat) { |
| 658 | dev_err(&pdev->dev, "no platform specific information\n"); | 658 | dev_err(&pdev->dev, "no platform specific information\n"); |
| 659 | goto exit_error; | 659 | goto exit_error; |
| @@ -803,3 +803,4 @@ module_exit(bf5xx_nand_exit); | |||
| 803 | MODULE_LICENSE("GPL"); | 803 | MODULE_LICENSE("GPL"); |
| 804 | MODULE_AUTHOR(DRV_AUTHOR); | 804 | MODULE_AUTHOR(DRV_AUTHOR); |
| 805 | MODULE_DESCRIPTION(DRV_DESC); | 805 | MODULE_DESCRIPTION(DRV_DESC); |
| 806 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c index 8dab69657b19..3370a800fd36 100644 --- a/drivers/mtd/nand/cs553x_nand.c +++ b/drivers/mtd/nand/cs553x_nand.c | |||
| @@ -279,7 +279,7 @@ static int is_geode(void) | |||
| 279 | 279 | ||
| 280 | 280 | ||
| 281 | #ifdef CONFIG_MTD_PARTITIONS | 281 | #ifdef CONFIG_MTD_PARTITIONS |
| 282 | const char *part_probes[] = { "cmdlinepart", NULL }; | 282 | static const char *part_probes[] = { "cmdlinepart", NULL }; |
| 283 | #endif | 283 | #endif |
| 284 | 284 | ||
| 285 | 285 | ||
diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c index 378b7aa63812..4b69aacdf5ca 100644 --- a/drivers/mtd/nand/fsl_elbc_nand.c +++ b/drivers/mtd/nand/fsl_elbc_nand.c | |||
| @@ -184,11 +184,11 @@ static int fsl_elbc_run_command(struct mtd_info *mtd) | |||
| 184 | in_be32(&lbc->fbar), in_be32(&lbc->fpar), | 184 | in_be32(&lbc->fbar), in_be32(&lbc->fpar), |
| 185 | in_be32(&lbc->fbcr), priv->bank); | 185 | in_be32(&lbc->fbcr), priv->bank); |
| 186 | 186 | ||
| 187 | ctrl->irq_status = 0; | ||
| 187 | /* execute special operation */ | 188 | /* execute special operation */ |
| 188 | out_be32(&lbc->lsor, priv->bank); | 189 | out_be32(&lbc->lsor, priv->bank); |
| 189 | 190 | ||
| 190 | /* wait for FCM complete flag or timeout */ | 191 | /* wait for FCM complete flag or timeout */ |
| 191 | ctrl->irq_status = 0; | ||
| 192 | wait_event_timeout(ctrl->irq_wait, ctrl->irq_status, | 192 | wait_event_timeout(ctrl->irq_wait, ctrl->irq_status, |
| 193 | FCM_TIMEOUT_MSECS * HZ/1000); | 193 | FCM_TIMEOUT_MSECS * HZ/1000); |
| 194 | ctrl->status = ctrl->irq_status; | 194 | ctrl->status = ctrl->irq_status; |
| @@ -346,19 +346,20 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command, | |||
| 346 | ctrl->column = column; | 346 | ctrl->column = column; |
| 347 | ctrl->oob = 0; | 347 | ctrl->oob = 0; |
| 348 | 348 | ||
| 349 | fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) | | ||
| 350 | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT); | ||
| 351 | |||
| 352 | if (priv->page_size) { | 349 | if (priv->page_size) { |
| 350 | fcr = (NAND_CMD_SEQIN << FCR_CMD0_SHIFT) | | ||
| 351 | (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT); | ||
| 352 | |||
| 353 | out_be32(&lbc->fir, | 353 | out_be32(&lbc->fir, |
| 354 | (FIR_OP_CW0 << FIR_OP0_SHIFT) | | 354 | (FIR_OP_CW0 << FIR_OP0_SHIFT) | |
| 355 | (FIR_OP_CA << FIR_OP1_SHIFT) | | 355 | (FIR_OP_CA << FIR_OP1_SHIFT) | |
| 356 | (FIR_OP_PA << FIR_OP2_SHIFT) | | 356 | (FIR_OP_PA << FIR_OP2_SHIFT) | |
| 357 | (FIR_OP_WB << FIR_OP3_SHIFT) | | 357 | (FIR_OP_WB << FIR_OP3_SHIFT) | |
| 358 | (FIR_OP_CW1 << FIR_OP4_SHIFT)); | 358 | (FIR_OP_CW1 << FIR_OP4_SHIFT)); |
| 359 | |||
| 360 | fcr |= NAND_CMD_READ0 << FCR_CMD0_SHIFT; | ||
| 361 | } else { | 359 | } else { |
| 360 | fcr = (NAND_CMD_PAGEPROG << FCR_CMD1_SHIFT) | | ||
| 361 | (NAND_CMD_SEQIN << FCR_CMD2_SHIFT); | ||
| 362 | |||
| 362 | out_be32(&lbc->fir, | 363 | out_be32(&lbc->fir, |
| 363 | (FIR_OP_CW0 << FIR_OP0_SHIFT) | | 364 | (FIR_OP_CW0 << FIR_OP0_SHIFT) | |
| 364 | (FIR_OP_CM2 << FIR_OP1_SHIFT) | | 365 | (FIR_OP_CM2 << FIR_OP1_SHIFT) | |
| @@ -480,7 +481,7 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | |||
| 480 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; | 481 | struct fsl_elbc_ctrl *ctrl = priv->ctrl; |
| 481 | unsigned int bufsize = mtd->writesize + mtd->oobsize; | 482 | unsigned int bufsize = mtd->writesize + mtd->oobsize; |
| 482 | 483 | ||
| 483 | if (len < 0) { | 484 | if (len <= 0) { |
| 484 | dev_err(ctrl->dev, "write_buf of %d bytes", len); | 485 | dev_err(ctrl->dev, "write_buf of %d bytes", len); |
| 485 | ctrl->status = 0; | 486 | ctrl->status = 0; |
| 486 | return; | 487 | return; |
| @@ -495,6 +496,15 @@ static void fsl_elbc_write_buf(struct mtd_info *mtd, const u8 *buf, int len) | |||
| 495 | } | 496 | } |
| 496 | 497 | ||
| 497 | memcpy_toio(&ctrl->addr[ctrl->index], buf, len); | 498 | memcpy_toio(&ctrl->addr[ctrl->index], buf, len); |
| 499 | /* | ||
| 500 | * This is workaround for the weird elbc hangs during nand write, | ||
| 501 | * Scott Wood says: "...perhaps difference in how long it takes a | ||
| 502 | * write to make it through the localbus compared to a write to IMMR | ||
| 503 | * is causing problems, and sync isn't helping for some reason." | ||
| 504 | * Reading back the last byte helps though. | ||
| 505 | */ | ||
| 506 | in_8(&ctrl->addr[ctrl->index] + len - 1); | ||
| 507 | |||
| 498 | ctrl->index += len; | 508 | ctrl->index += len; |
| 499 | } | 509 | } |
| 500 | 510 | ||
| @@ -666,7 +676,7 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | |||
| 666 | /* adjust Option Register and ECC to match Flash page size */ | 676 | /* adjust Option Register and ECC to match Flash page size */ |
| 667 | if (mtd->writesize == 512) { | 677 | if (mtd->writesize == 512) { |
| 668 | priv->page_size = 0; | 678 | priv->page_size = 0; |
| 669 | clrbits32(&lbc->bank[priv->bank].or, ~OR_FCM_PGS); | 679 | clrbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS); |
| 670 | } else if (mtd->writesize == 2048) { | 680 | } else if (mtd->writesize == 2048) { |
| 671 | priv->page_size = 1; | 681 | priv->page_size = 1; |
| 672 | setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS); | 682 | setbits32(&lbc->bank[priv->bank].or, OR_FCM_PGS); |
| @@ -687,11 +697,6 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd) | |||
| 687 | return -1; | 697 | return -1; |
| 688 | } | 698 | } |
| 689 | 699 | ||
| 690 | /* The default u-boot configuration on MPC8313ERDB causes errors; | ||
| 691 | * more delay is needed. This should be safe for other boards | ||
| 692 | * as well. | ||
| 693 | */ | ||
| 694 | setbits32(&lbc->bank[priv->bank].or, 0x70); | ||
| 695 | return 0; | 700 | return 0; |
| 696 | } | 701 | } |
| 697 | 702 | ||
| @@ -779,6 +784,8 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv) | |||
| 779 | 784 | ||
| 780 | nand_release(&priv->mtd); | 785 | nand_release(&priv->mtd); |
| 781 | 786 | ||
| 787 | kfree(priv->mtd.name); | ||
| 788 | |||
| 782 | if (priv->vbase) | 789 | if (priv->vbase) |
| 783 | iounmap(priv->vbase); | 790 | iounmap(priv->vbase); |
| 784 | 791 | ||
| @@ -839,6 +846,12 @@ static int fsl_elbc_chip_probe(struct fsl_elbc_ctrl *ctrl, | |||
| 839 | goto err; | 846 | goto err; |
| 840 | } | 847 | } |
| 841 | 848 | ||
| 849 | priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", res.start); | ||
| 850 | if (!priv->mtd.name) { | ||
| 851 | ret = -ENOMEM; | ||
| 852 | goto err; | ||
| 853 | } | ||
| 854 | |||
| 842 | ret = fsl_elbc_chip_init(priv); | 855 | ret = fsl_elbc_chip_init(priv); |
| 843 | if (ret) | 856 | if (ret) |
| 844 | goto err; | 857 | goto err; |
diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c new file mode 100644 index 000000000000..1ebfd87f00b4 --- /dev/null +++ b/drivers/mtd/nand/fsl_upm.c | |||
| @@ -0,0 +1,291 @@ | |||
| 1 | /* | ||
| 2 | * Freescale UPM NAND driver. | ||
| 3 | * | ||
| 4 | * Copyright © 2007-2008 MontaVista Software, Inc. | ||
| 5 | * | ||
| 6 | * Author: Anton Vorontsov <avorontsov@ru.mvista.com> | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/kernel.h> | ||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/mtd/nand.h> | ||
| 17 | #include <linux/mtd/nand_ecc.h> | ||
| 18 | #include <linux/mtd/partitions.h> | ||
| 19 | #include <linux/mtd/mtd.h> | ||
| 20 | #include <linux/of_platform.h> | ||
| 21 | #include <linux/of_gpio.h> | ||
| 22 | #include <linux/io.h> | ||
| 23 | #include <asm/fsl_lbc.h> | ||
| 24 | |||
| 25 | struct fsl_upm_nand { | ||
| 26 | struct device *dev; | ||
| 27 | struct mtd_info mtd; | ||
| 28 | struct nand_chip chip; | ||
| 29 | int last_ctrl; | ||
| 30 | #ifdef CONFIG_MTD_PARTITIONS | ||
| 31 | struct mtd_partition *parts; | ||
| 32 | #endif | ||
| 33 | |||
| 34 | struct fsl_upm upm; | ||
| 35 | uint8_t upm_addr_offset; | ||
| 36 | uint8_t upm_cmd_offset; | ||
| 37 | void __iomem *io_base; | ||
| 38 | int rnb_gpio; | ||
| 39 | const uint32_t *wait_pattern; | ||
| 40 | const uint32_t *wait_write; | ||
| 41 | int chip_delay; | ||
| 42 | }; | ||
| 43 | |||
| 44 | #define to_fsl_upm_nand(mtd) container_of(mtd, struct fsl_upm_nand, mtd) | ||
| 45 | |||
| 46 | static int fun_chip_ready(struct mtd_info *mtd) | ||
| 47 | { | ||
| 48 | struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); | ||
| 49 | |||
| 50 | if (gpio_get_value(fun->rnb_gpio)) | ||
| 51 | return 1; | ||
| 52 | |||
| 53 | dev_vdbg(fun->dev, "busy\n"); | ||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | static void fun_wait_rnb(struct fsl_upm_nand *fun) | ||
| 58 | { | ||
| 59 | int cnt = 1000000; | ||
| 60 | |||
| 61 | if (fun->rnb_gpio >= 0) { | ||
| 62 | while (--cnt && !fun_chip_ready(&fun->mtd)) | ||
| 63 | cpu_relax(); | ||
| 64 | } | ||
| 65 | |||
| 66 | if (!cnt) | ||
| 67 | dev_err(fun->dev, "tired waiting for RNB\n"); | ||
| 68 | } | ||
| 69 | |||
| 70 | static void fun_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl) | ||
| 71 | { | ||
| 72 | struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); | ||
| 73 | |||
| 74 | if (!(ctrl & fun->last_ctrl)) { | ||
| 75 | fsl_upm_end_pattern(&fun->upm); | ||
| 76 | |||
| 77 | if (cmd == NAND_CMD_NONE) | ||
| 78 | return; | ||
| 79 | |||
| 80 | fun->last_ctrl = ctrl & (NAND_ALE | NAND_CLE); | ||
| 81 | } | ||
| 82 | |||
| 83 | if (ctrl & NAND_CTRL_CHANGE) { | ||
| 84 | if (ctrl & NAND_ALE) | ||
| 85 | fsl_upm_start_pattern(&fun->upm, fun->upm_addr_offset); | ||
| 86 | else if (ctrl & NAND_CLE) | ||
| 87 | fsl_upm_start_pattern(&fun->upm, fun->upm_cmd_offset); | ||
| 88 | } | ||
| 89 | |||
| 90 | fsl_upm_run_pattern(&fun->upm, fun->io_base, cmd); | ||
| 91 | |||
| 92 | if (fun->wait_pattern) | ||
| 93 | fun_wait_rnb(fun); | ||
| 94 | } | ||
| 95 | |||
| 96 | static uint8_t fun_read_byte(struct mtd_info *mtd) | ||
| 97 | { | ||
| 98 | struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); | ||
| 99 | |||
| 100 | return in_8(fun->chip.IO_ADDR_R); | ||
| 101 | } | ||
| 102 | |||
| 103 | static void fun_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | ||
| 104 | { | ||
| 105 | struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); | ||
| 106 | int i; | ||
| 107 | |||
| 108 | for (i = 0; i < len; i++) | ||
| 109 | buf[i] = in_8(fun->chip.IO_ADDR_R); | ||
| 110 | } | ||
| 111 | |||
| 112 | static void fun_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len) | ||
| 113 | { | ||
| 114 | struct fsl_upm_nand *fun = to_fsl_upm_nand(mtd); | ||
| 115 | int i; | ||
| 116 | |||
| 117 | for (i = 0; i < len; i++) { | ||
| 118 | out_8(fun->chip.IO_ADDR_W, buf[i]); | ||
| 119 | if (fun->wait_write) | ||
| 120 | fun_wait_rnb(fun); | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | static int __devinit fun_chip_init(struct fsl_upm_nand *fun) | ||
| 125 | { | ||
| 126 | int ret; | ||
| 127 | #ifdef CONFIG_MTD_PARTITIONS | ||
| 128 | static const char *part_types[] = { "cmdlinepart", NULL, }; | ||
| 129 | #endif | ||
| 130 | |||
| 131 | fun->chip.IO_ADDR_R = fun->io_base; | ||
| 132 | fun->chip.IO_ADDR_W = fun->io_base; | ||
| 133 | fun->chip.cmd_ctrl = fun_cmd_ctrl; | ||
| 134 | fun->chip.chip_delay = fun->chip_delay; | ||
| 135 | fun->chip.read_byte = fun_read_byte; | ||
| 136 | fun->chip.read_buf = fun_read_buf; | ||
| 137 | fun->chip.write_buf = fun_write_buf; | ||
| 138 | fun->chip.ecc.mode = NAND_ECC_SOFT; | ||
| 139 | |||
| 140 | if (fun->rnb_gpio >= 0) | ||
| 141 | fun->chip.dev_ready = fun_chip_ready; | ||
| 142 | |||
| 143 | fun->mtd.priv = &fun->chip; | ||
| 144 | fun->mtd.owner = THIS_MODULE; | ||
| 145 | |||
| 146 | ret = nand_scan(&fun->mtd, 1); | ||
| 147 | if (ret) | ||
| 148 | return ret; | ||
| 149 | |||
| 150 | fun->mtd.name = fun->dev->bus_id; | ||
| 151 | |||
| 152 | #ifdef CONFIG_MTD_PARTITIONS | ||
| 153 | ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0); | ||
| 154 | if (ret > 0) | ||
| 155 | return add_mtd_partitions(&fun->mtd, fun->parts, ret); | ||
| 156 | #endif | ||
| 157 | return add_mtd_device(&fun->mtd); | ||
| 158 | } | ||
| 159 | |||
| 160 | static int __devinit fun_probe(struct of_device *ofdev, | ||
| 161 | const struct of_device_id *ofid) | ||
| 162 | { | ||
| 163 | struct fsl_upm_nand *fun; | ||
| 164 | struct resource io_res; | ||
| 165 | const uint32_t *prop; | ||
| 166 | int ret; | ||
| 167 | int size; | ||
| 168 | |||
| 169 | fun = kzalloc(sizeof(*fun), GFP_KERNEL); | ||
| 170 | if (!fun) | ||
| 171 | return -ENOMEM; | ||
| 172 | |||
| 173 | ret = of_address_to_resource(ofdev->node, 0, &io_res); | ||
| 174 | if (ret) { | ||
| 175 | dev_err(&ofdev->dev, "can't get IO base\n"); | ||
| 176 | goto err1; | ||
| 177 | } | ||
| 178 | |||
| 179 | ret = fsl_upm_find(io_res.start, &fun->upm); | ||
| 180 | if (ret) { | ||
| 181 | dev_err(&ofdev->dev, "can't find UPM\n"); | ||
| 182 | goto err1; | ||
| 183 | } | ||
| 184 | |||
| 185 | prop = of_get_property(ofdev->node, "fsl,upm-addr-offset", &size); | ||
| 186 | if (!prop || size != sizeof(uint32_t)) { | ||
| 187 | dev_err(&ofdev->dev, "can't get UPM address offset\n"); | ||
| 188 | ret = -EINVAL; | ||
| 189 | goto err2; | ||
| 190 | } | ||
| 191 | fun->upm_addr_offset = *prop; | ||
| 192 | |||
| 193 | prop = of_get_property(ofdev->node, "fsl,upm-cmd-offset", &size); | ||
| 194 | if (!prop || size != sizeof(uint32_t)) { | ||
| 195 | dev_err(&ofdev->dev, "can't get UPM command offset\n"); | ||
| 196 | ret = -EINVAL; | ||
| 197 | goto err2; | ||
| 198 | } | ||
| 199 | fun->upm_cmd_offset = *prop; | ||
| 200 | |||
| 201 | fun->rnb_gpio = of_get_gpio(ofdev->node, 0); | ||
| 202 | if (fun->rnb_gpio >= 0) { | ||
| 203 | ret = gpio_request(fun->rnb_gpio, ofdev->dev.bus_id); | ||
| 204 | if (ret) { | ||
| 205 | dev_err(&ofdev->dev, "can't request RNB gpio\n"); | ||
| 206 | goto err2; | ||
| 207 | } | ||
| 208 | gpio_direction_input(fun->rnb_gpio); | ||
| 209 | } else if (fun->rnb_gpio == -EINVAL) { | ||
| 210 | dev_err(&ofdev->dev, "specified RNB gpio is invalid\n"); | ||
| 211 | goto err2; | ||
| 212 | } | ||
| 213 | |||
| 214 | fun->io_base = devm_ioremap_nocache(&ofdev->dev, io_res.start, | ||
| 215 | io_res.end - io_res.start + 1); | ||
| 216 | if (!fun->io_base) { | ||
| 217 | ret = -ENOMEM; | ||
| 218 | goto err2; | ||
| 219 | } | ||
| 220 | |||
| 221 | fun->dev = &ofdev->dev; | ||
| 222 | fun->last_ctrl = NAND_CLE; | ||
| 223 | fun->wait_pattern = of_get_property(ofdev->node, "fsl,wait-pattern", | ||
| 224 | NULL); | ||
| 225 | fun->wait_write = of_get_property(ofdev->node, "fsl,wait-write", NULL); | ||
| 226 | |||
| 227 | prop = of_get_property(ofdev->node, "chip-delay", NULL); | ||
| 228 | if (prop) | ||
| 229 | fun->chip_delay = *prop; | ||
| 230 | else | ||
| 231 | fun->chip_delay = 50; | ||
| 232 | |||
| 233 | ret = fun_chip_init(fun); | ||
| 234 | if (ret) | ||
| 235 | goto err2; | ||
| 236 | |||
| 237 | dev_set_drvdata(&ofdev->dev, fun); | ||
| 238 | |||
| 239 | return 0; | ||
| 240 | err2: | ||
| 241 | if (fun->rnb_gpio >= 0) | ||
| 242 | gpio_free(fun->rnb_gpio); | ||
| 243 | err1: | ||
| 244 | kfree(fun); | ||
| 245 | |||
| 246 | return ret; | ||
| 247 | } | ||
| 248 | |||
| 249 | static int __devexit fun_remove(struct of_device *ofdev) | ||
| 250 | { | ||
| 251 | struct fsl_upm_nand *fun = dev_get_drvdata(&ofdev->dev); | ||
| 252 | |||
| 253 | nand_release(&fun->mtd); | ||
| 254 | |||
| 255 | if (fun->rnb_gpio >= 0) | ||
| 256 | gpio_free(fun->rnb_gpio); | ||
| 257 | |||
| 258 | kfree(fun); | ||
| 259 | |||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | static struct of_device_id of_fun_match[] = { | ||
| 264 | { .compatible = "fsl,upm-nand" }, | ||
| 265 | {}, | ||
| 266 | }; | ||
| 267 | MODULE_DEVICE_TABLE(of, of_fun_match); | ||
| 268 | |||
| 269 | static struct of_platform_driver of_fun_driver = { | ||
| 270 | .name = "fsl,upm-nand", | ||
| 271 | .match_table = of_fun_match, | ||
| 272 | .probe = fun_probe, | ||
| 273 | .remove = __devexit_p(fun_remove), | ||
| 274 | }; | ||
| 275 | |||
| 276 | static int __init fun_module_init(void) | ||
| 277 | { | ||
| 278 | return of_register_platform_driver(&of_fun_driver); | ||
| 279 | } | ||
| 280 | module_init(fun_module_init); | ||
| 281 | |||
| 282 | static void __exit fun_module_exit(void) | ||
| 283 | { | ||
| 284 | of_unregister_platform_driver(&of_fun_driver); | ||
| 285 | } | ||
| 286 | module_exit(fun_module_exit); | ||
| 287 | |||
| 288 | MODULE_LICENSE("GPL"); | ||
| 289 | MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>"); | ||
| 290 | MODULE_DESCRIPTION("Driver for NAND chips working through Freescale " | ||
| 291 | "LocalBus User-Programmable Machine"); | ||
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 7acb1a0e7409..ba1bdf787323 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
| @@ -2229,6 +2229,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
| 2229 | { | 2229 | { |
| 2230 | struct nand_flash_dev *type = NULL; | 2230 | struct nand_flash_dev *type = NULL; |
| 2231 | int i, dev_id, maf_idx; | 2231 | int i, dev_id, maf_idx; |
| 2232 | int tmp_id, tmp_manf; | ||
| 2232 | 2233 | ||
| 2233 | /* Select the device */ | 2234 | /* Select the device */ |
| 2234 | chip->select_chip(mtd, 0); | 2235 | chip->select_chip(mtd, 0); |
| @@ -2240,6 +2241,26 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, | |||
| 2240 | *maf_id = chip->read_byte(mtd); | 2241 | *maf_id = chip->read_byte(mtd); |
| 2241 | dev_id = chip->read_byte(mtd); | 2242 | dev_id = chip->read_byte(mtd); |
| 2242 | 2243 | ||
| 2244 | /* Try again to make sure, as some systems the bus-hold or other | ||
| 2245 | * interface concerns can cause random data which looks like a | ||
| 2246 | * possibly credible NAND flash to appear. If the two results do | ||
| 2247 | * not match, ignore the device completely. | ||
| 2248 | */ | ||
| 2249 | |||
| 2250 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); | ||
| 2251 | |||
| 2252 | /* Read manufacturer and device IDs */ | ||
| 2253 | |||
| 2254 | tmp_manf = chip->read_byte(mtd); | ||
| 2255 | tmp_id = chip->read_byte(mtd); | ||
| 2256 | |||
| 2257 | if (tmp_manf != *maf_id || tmp_id != dev_id) { | ||
| 2258 | printk(KERN_INFO "%s: second ID read did not match " | ||
| 2259 | "%02x,%02x against %02x,%02x\n", __func__, | ||
| 2260 | *maf_id, dev_id, tmp_manf, tmp_id); | ||
| 2261 | return ERR_PTR(-ENODEV); | ||
| 2262 | } | ||
| 2263 | |||
| 2243 | /* Lookup the flash id */ | 2264 | /* Lookup the flash id */ |
| 2244 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { | 2265 | for (i = 0; nand_flash_ids[i].name != NULL; i++) { |
| 2245 | if (dev_id == nand_flash_ids[i].id) { | 2266 | if (dev_id == nand_flash_ids[i].id) { |
diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 1c0e89f00e8d..955959eb02d4 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c | |||
| @@ -317,3 +317,5 @@ module_exit(ndfc_nand_exit); | |||
| 317 | MODULE_LICENSE("GPL"); | 317 | MODULE_LICENSE("GPL"); |
| 318 | MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); | 318 | MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>"); |
| 319 | MODULE_DESCRIPTION("Platform driver for NDFC"); | 319 | MODULE_DESCRIPTION("Platform driver for NDFC"); |
| 320 | MODULE_ALIAS("platform:ndfc-chip"); | ||
| 321 | MODULE_ALIAS("platform:ndfc-nand"); | ||
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c index ec5ad28b237e..59e05a1c50cf 100644 --- a/drivers/mtd/nand/orion_nand.c +++ b/drivers/mtd/nand/orion_nand.c | |||
| @@ -169,3 +169,4 @@ module_exit(orion_nand_exit); | |||
| 169 | MODULE_LICENSE("GPL"); | 169 | MODULE_LICENSE("GPL"); |
| 170 | MODULE_AUTHOR("Tzachi Perelstein"); | 170 | MODULE_AUTHOR("Tzachi Perelstein"); |
| 171 | MODULE_DESCRIPTION("NAND glue for Orion platforms"); | 171 | MODULE_DESCRIPTION("NAND glue for Orion platforms"); |
| 172 | MODULE_ALIAS("platform:orion_nand"); | ||
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c index f6d5c2adc4fd..f674c5427b17 100644 --- a/drivers/mtd/nand/plat_nand.c +++ b/drivers/mtd/nand/plat_nand.c | |||
| @@ -54,6 +54,7 @@ static int __init plat_nand_probe(struct platform_device *pdev) | |||
| 54 | data->chip.priv = &data; | 54 | data->chip.priv = &data; |
| 55 | data->mtd.priv = &data->chip; | 55 | data->mtd.priv = &data->chip; |
| 56 | data->mtd.owner = THIS_MODULE; | 56 | data->mtd.owner = THIS_MODULE; |
| 57 | data->mtd.name = pdev->dev.bus_id; | ||
| 57 | 58 | ||
| 58 | data->chip.IO_ADDR_R = data->io_base; | 59 | data->chip.IO_ADDR_R = data->io_base; |
| 59 | data->chip.IO_ADDR_W = data->io_base; | 60 | data->chip.IO_ADDR_W = data->io_base; |
| @@ -150,3 +151,4 @@ module_exit(plat_nand_exit); | |||
| 150 | MODULE_LICENSE("GPL"); | 151 | MODULE_LICENSE("GPL"); |
| 151 | MODULE_AUTHOR("Vitaly Wool"); | 152 | MODULE_AUTHOR("Vitaly Wool"); |
| 152 | MODULE_DESCRIPTION("Simple generic NAND driver"); | 153 | MODULE_DESCRIPTION("Simple generic NAND driver"); |
| 154 | MODULE_ALIAS("platform:gen_nand"); | ||
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c new file mode 100644 index 000000000000..fceb468ccdec --- /dev/null +++ b/drivers/mtd/nand/pxa3xx_nand.c | |||
| @@ -0,0 +1,1249 @@ | |||
| 1 | /* | ||
| 2 | * drivers/mtd/nand/pxa3xx_nand.c | ||
| 3 | * | ||
| 4 | * Copyright © 2005 Intel Corporation | ||
| 5 | * Copyright © 2006 Marvell International Ltd. | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License version 2 as | ||
| 9 | * published by the Free Software Foundation. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/interrupt.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/dma-mapping.h> | ||
| 16 | #include <linux/delay.h> | ||
| 17 | #include <linux/clk.h> | ||
| 18 | #include <linux/mtd/mtd.h> | ||
| 19 | #include <linux/mtd/nand.h> | ||
| 20 | #include <linux/mtd/partitions.h> | ||
| 21 | #include <linux/io.h> | ||
| 22 | #include <linux/irq.h> | ||
| 23 | #include <asm/dma.h> | ||
| 24 | |||
| 25 | #include <asm/arch/pxa-regs.h> | ||
| 26 | #include <asm/arch/pxa3xx_nand.h> | ||
| 27 | |||
| 28 | #define CHIP_DELAY_TIMEOUT (2 * HZ/10) | ||
| 29 | |||
| 30 | /* registers and bit definitions */ | ||
| 31 | #define NDCR (0x00) /* Control register */ | ||
| 32 | #define NDTR0CS0 (0x04) /* Timing Parameter 0 for CS0 */ | ||
| 33 | #define NDTR1CS0 (0x0C) /* Timing Parameter 1 for CS0 */ | ||
| 34 | #define NDSR (0x14) /* Status Register */ | ||
| 35 | #define NDPCR (0x18) /* Page Count Register */ | ||
| 36 | #define NDBDR0 (0x1C) /* Bad Block Register 0 */ | ||
| 37 | #define NDBDR1 (0x20) /* Bad Block Register 1 */ | ||
| 38 | #define NDDB (0x40) /* Data Buffer */ | ||
| 39 | #define NDCB0 (0x48) /* Command Buffer0 */ | ||
| 40 | #define NDCB1 (0x4C) /* Command Buffer1 */ | ||
| 41 | #define NDCB2 (0x50) /* Command Buffer2 */ | ||
| 42 | |||
| 43 | #define NDCR_SPARE_EN (0x1 << 31) | ||
| 44 | #define NDCR_ECC_EN (0x1 << 30) | ||
| 45 | #define NDCR_DMA_EN (0x1 << 29) | ||
| 46 | #define NDCR_ND_RUN (0x1 << 28) | ||
| 47 | #define NDCR_DWIDTH_C (0x1 << 27) | ||
| 48 | #define NDCR_DWIDTH_M (0x1 << 26) | ||
| 49 | #define NDCR_PAGE_SZ (0x1 << 24) | ||
| 50 | #define NDCR_NCSX (0x1 << 23) | ||
| 51 | #define NDCR_ND_MODE (0x3 << 21) | ||
| 52 | #define NDCR_NAND_MODE (0x0) | ||
| 53 | #define NDCR_CLR_PG_CNT (0x1 << 20) | ||
| 54 | #define NDCR_CLR_ECC (0x1 << 19) | ||
| 55 | #define NDCR_RD_ID_CNT_MASK (0x7 << 16) | ||
| 56 | #define NDCR_RD_ID_CNT(x) (((x) << 16) & NDCR_RD_ID_CNT_MASK) | ||
| 57 | |||
| 58 | #define NDCR_RA_START (0x1 << 15) | ||
| 59 | #define NDCR_PG_PER_BLK (0x1 << 14) | ||
| 60 | #define NDCR_ND_ARB_EN (0x1 << 12) | ||
| 61 | |||
| 62 | #define NDSR_MASK (0xfff) | ||
| 63 | #define NDSR_RDY (0x1 << 11) | ||
| 64 | #define NDSR_CS0_PAGED (0x1 << 10) | ||
| 65 | #define NDSR_CS1_PAGED (0x1 << 9) | ||
| 66 | #define NDSR_CS0_CMDD (0x1 << 8) | ||
| 67 | #define NDSR_CS1_CMDD (0x1 << 7) | ||
| 68 | #define NDSR_CS0_BBD (0x1 << 6) | ||
| 69 | #define NDSR_CS1_BBD (0x1 << 5) | ||
| 70 | #define NDSR_DBERR (0x1 << 4) | ||
| 71 | #define NDSR_SBERR (0x1 << 3) | ||
| 72 | #define NDSR_WRDREQ (0x1 << 2) | ||
| 73 | #define NDSR_RDDREQ (0x1 << 1) | ||
| 74 | #define NDSR_WRCMDREQ (0x1) | ||
| 75 | |||
| 76 | #define NDCB0_AUTO_RS (0x1 << 25) | ||
| 77 | #define NDCB0_CSEL (0x1 << 24) | ||
| 78 | #define NDCB0_CMD_TYPE_MASK (0x7 << 21) | ||
| 79 | #define NDCB0_CMD_TYPE(x) (((x) << 21) & NDCB0_CMD_TYPE_MASK) | ||
| 80 | #define NDCB0_NC (0x1 << 20) | ||
| 81 | #define NDCB0_DBC (0x1 << 19) | ||
| 82 | #define NDCB0_ADDR_CYC_MASK (0x7 << 16) | ||
| 83 | #define NDCB0_ADDR_CYC(x) (((x) << 16) & NDCB0_ADDR_CYC_MASK) | ||
| 84 | #define NDCB0_CMD2_MASK (0xff << 8) | ||
| 85 | #define NDCB0_CMD1_MASK (0xff) | ||
| 86 | #define NDCB0_ADDR_CYC_SHIFT (16) | ||
| 87 | |||
| 88 | /* dma-able I/O address for the NAND data and commands */ | ||
| 89 | #define NDCB0_DMA_ADDR (0x43100048) | ||
| 90 | #define NDDB_DMA_ADDR (0x43100040) | ||
| 91 | |||
| 92 | /* macros for registers read/write */ | ||
| 93 | #define nand_writel(info, off, val) \ | ||
| 94 | __raw_writel((val), (info)->mmio_base + (off)) | ||
| 95 | |||
| 96 | #define nand_readl(info, off) \ | ||
| 97 | __raw_readl((info)->mmio_base + (off)) | ||
| 98 | |||
| 99 | /* error code and state */ | ||
| 100 | enum { | ||
| 101 | ERR_NONE = 0, | ||
| 102 | ERR_DMABUSERR = -1, | ||
| 103 | ERR_SENDCMD = -2, | ||
| 104 | ERR_DBERR = -3, | ||
| 105 | ERR_BBERR = -4, | ||
| 106 | }; | ||
| 107 | |||
| 108 | enum { | ||
| 109 | STATE_READY = 0, | ||
| 110 | STATE_CMD_HANDLE, | ||
| 111 | STATE_DMA_READING, | ||
| 112 | STATE_DMA_WRITING, | ||
| 113 | STATE_DMA_DONE, | ||
| 114 | STATE_PIO_READING, | ||
| 115 | STATE_PIO_WRITING, | ||
| 116 | }; | ||
| 117 | |||
| 118 | struct pxa3xx_nand_timing { | ||
| 119 | unsigned int tCH; /* Enable signal hold time */ | ||
| 120 | unsigned int tCS; /* Enable signal setup time */ | ||
| 121 | unsigned int tWH; /* ND_nWE high duration */ | ||
| 122 | unsigned int tWP; /* ND_nWE pulse time */ | ||
| 123 | unsigned int tRH; /* ND_nRE high duration */ | ||
| 124 | unsigned int tRP; /* ND_nRE pulse width */ | ||
| 125 | unsigned int tR; /* ND_nWE high to ND_nRE low for read */ | ||
| 126 | unsigned int tWHR; /* ND_nWE high to ND_nRE low for status read */ | ||
| 127 | unsigned int tAR; /* ND_ALE low to ND_nRE low delay */ | ||
| 128 | }; | ||
| 129 | |||
| 130 | struct pxa3xx_nand_cmdset { | ||
| 131 | uint16_t read1; | ||
| 132 | uint16_t read2; | ||
| 133 | uint16_t program; | ||
| 134 | uint16_t read_status; | ||
| 135 | uint16_t read_id; | ||
| 136 | uint16_t erase; | ||
| 137 | uint16_t reset; | ||
| 138 | uint16_t lock; | ||
| 139 | uint16_t unlock; | ||
| 140 | uint16_t lock_status; | ||
| 141 | }; | ||
| 142 | |||
| 143 | struct pxa3xx_nand_flash { | ||
| 144 | struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ | ||
| 145 | struct pxa3xx_nand_cmdset *cmdset; | ||
| 146 | |||
| 147 | uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */ | ||
| 148 | uint32_t page_size; /* Page size in bytes (PAGE_SZ) */ | ||
| 149 | uint32_t flash_width; /* Width of Flash memory (DWIDTH_M) */ | ||
| 150 | uint32_t dfc_width; /* Width of flash controller(DWIDTH_C) */ | ||
| 151 | uint32_t num_blocks; /* Number of physical blocks in Flash */ | ||
| 152 | uint32_t chip_id; | ||
| 153 | |||
| 154 | /* NOTE: these are automatically calculated, do not define */ | ||
| 155 | size_t oob_size; | ||
| 156 | size_t read_id_bytes; | ||
| 157 | |||
| 158 | unsigned int col_addr_cycles; | ||
| 159 | unsigned int row_addr_cycles; | ||
| 160 | }; | ||
| 161 | |||
| 162 | struct pxa3xx_nand_info { | ||
| 163 | struct nand_chip nand_chip; | ||
| 164 | |||
| 165 | struct platform_device *pdev; | ||
| 166 | struct pxa3xx_nand_flash *flash_info; | ||
| 167 | |||
| 168 | struct clk *clk; | ||
| 169 | void __iomem *mmio_base; | ||
| 170 | |||
| 171 | unsigned int buf_start; | ||
| 172 | unsigned int buf_count; | ||
| 173 | |||
| 174 | /* DMA information */ | ||
| 175 | int drcmr_dat; | ||
| 176 | int drcmr_cmd; | ||
| 177 | |||
| 178 | unsigned char *data_buff; | ||
| 179 | dma_addr_t data_buff_phys; | ||
| 180 | size_t data_buff_size; | ||
| 181 | int data_dma_ch; | ||
| 182 | struct pxa_dma_desc *data_desc; | ||
| 183 | dma_addr_t data_desc_addr; | ||
| 184 | |||
| 185 | uint32_t reg_ndcr; | ||
| 186 | |||
| 187 | /* saved column/page_addr during CMD_SEQIN */ | ||
| 188 | int seqin_column; | ||
| 189 | int seqin_page_addr; | ||
| 190 | |||
| 191 | /* relate to the command */ | ||
| 192 | unsigned int state; | ||
| 193 | |||
| 194 | int use_ecc; /* use HW ECC ? */ | ||
| 195 | int use_dma; /* use DMA ? */ | ||
| 196 | |||
| 197 | size_t data_size; /* data size in FIFO */ | ||
| 198 | int retcode; | ||
| 199 | struct completion cmd_complete; | ||
| 200 | |||
| 201 | /* generated NDCBx register values */ | ||
| 202 | uint32_t ndcb0; | ||
| 203 | uint32_t ndcb1; | ||
| 204 | uint32_t ndcb2; | ||
| 205 | }; | ||
| 206 | |||
| 207 | static int use_dma = 1; | ||
| 208 | module_param(use_dma, bool, 0444); | ||
| 209 | MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW"); | ||
| 210 | |||
| 211 | static struct pxa3xx_nand_cmdset smallpage_cmdset = { | ||
| 212 | .read1 = 0x0000, | ||
| 213 | .read2 = 0x0050, | ||
| 214 | .program = 0x1080, | ||
| 215 | .read_status = 0x0070, | ||
| 216 | .read_id = 0x0090, | ||
| 217 | .erase = 0xD060, | ||
| 218 | .reset = 0x00FF, | ||
| 219 | .lock = 0x002A, | ||
| 220 | .unlock = 0x2423, | ||
| 221 | .lock_status = 0x007A, | ||
| 222 | }; | ||
| 223 | |||
| 224 | static struct pxa3xx_nand_cmdset largepage_cmdset = { | ||
| 225 | .read1 = 0x3000, | ||
| 226 | .read2 = 0x0050, | ||
| 227 | .program = 0x1080, | ||
| 228 | .read_status = 0x0070, | ||
| 229 | .read_id = 0x0090, | ||
| 230 | .erase = 0xD060, | ||
| 231 | .reset = 0x00FF, | ||
| 232 | .lock = 0x002A, | ||
| 233 | .unlock = 0x2423, | ||
| 234 | .lock_status = 0x007A, | ||
| 235 | }; | ||
| 236 | |||
| 237 | static struct pxa3xx_nand_timing samsung512MbX16_timing = { | ||
| 238 | .tCH = 10, | ||
| 239 | .tCS = 0, | ||
| 240 | .tWH = 20, | ||
| 241 | .tWP = 40, | ||
| 242 | .tRH = 30, | ||
| 243 | .tRP = 40, | ||
| 244 | .tR = 11123, | ||
| 245 | .tWHR = 110, | ||
| 246 | .tAR = 10, | ||
| 247 | }; | ||
| 248 | |||
| 249 | static struct pxa3xx_nand_flash samsung512MbX16 = { | ||
| 250 | .timing = &samsung512MbX16_timing, | ||
| 251 | .cmdset = &smallpage_cmdset, | ||
| 252 | .page_per_block = 32, | ||
| 253 | .page_size = 512, | ||
| 254 | .flash_width = 16, | ||
| 255 | .dfc_width = 16, | ||
| 256 | .num_blocks = 4096, | ||
| 257 | .chip_id = 0x46ec, | ||
| 258 | }; | ||
| 259 | |||
| 260 | static struct pxa3xx_nand_timing micron_timing = { | ||
| 261 | .tCH = 10, | ||
| 262 | .tCS = 25, | ||
| 263 | .tWH = 15, | ||
| 264 | .tWP = 25, | ||
| 265 | .tRH = 15, | ||
| 266 | .tRP = 25, | ||
| 267 | .tR = 25000, | ||
| 268 | .tWHR = 60, | ||
| 269 | .tAR = 10, | ||
| 270 | }; | ||
| 271 | |||
| 272 | static struct pxa3xx_nand_flash micron1GbX8 = { | ||
| 273 | .timing = µn_timing, | ||
| 274 | .cmdset = &largepage_cmdset, | ||
| 275 | .page_per_block = 64, | ||
| 276 | .page_size = 2048, | ||
| 277 | .flash_width = 8, | ||
| 278 | .dfc_width = 8, | ||
| 279 | .num_blocks = 1024, | ||
| 280 | .chip_id = 0xa12c, | ||
| 281 | }; | ||
| 282 | |||
| 283 | static struct pxa3xx_nand_flash micron1GbX16 = { | ||
| 284 | .timing = µn_timing, | ||
| 285 | .cmdset = &largepage_cmdset, | ||
| 286 | .page_per_block = 64, | ||
| 287 | .page_size = 2048, | ||
| 288 | .flash_width = 16, | ||
| 289 | .dfc_width = 16, | ||
| 290 | .num_blocks = 1024, | ||
| 291 | .chip_id = 0xb12c, | ||
| 292 | }; | ||
| 293 | |||
| 294 | static struct pxa3xx_nand_flash *builtin_flash_types[] = { | ||
| 295 | &samsung512MbX16, | ||
| 296 | µn1GbX8, | ||
| 297 | µn1GbX16, | ||
| 298 | }; | ||
| 299 | |||
| 300 | #define NDTR0_tCH(c) (min((c), 7) << 19) | ||
| 301 | #define NDTR0_tCS(c) (min((c), 7) << 16) | ||
| 302 | #define NDTR0_tWH(c) (min((c), 7) << 11) | ||
| 303 | #define NDTR0_tWP(c) (min((c), 7) << 8) | ||
| 304 | #define NDTR0_tRH(c) (min((c), 7) << 3) | ||
| 305 | #define NDTR0_tRP(c) (min((c), 7) << 0) | ||
| 306 | |||
| 307 | #define NDTR1_tR(c) (min((c), 65535) << 16) | ||
| 308 | #define NDTR1_tWHR(c) (min((c), 15) << 4) | ||
| 309 | #define NDTR1_tAR(c) (min((c), 15) << 0) | ||
| 310 | |||
| 311 | /* convert nano-seconds to nand flash controller clock cycles */ | ||
| 312 | #define ns2cycle(ns, clk) (int)(((ns) * (clk / 1000000) / 1000) + 1) | ||
| 313 | |||
| 314 | static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, | ||
| 315 | struct pxa3xx_nand_timing *t) | ||
| 316 | { | ||
| 317 | unsigned long nand_clk = clk_get_rate(info->clk); | ||
| 318 | uint32_t ndtr0, ndtr1; | ||
| 319 | |||
| 320 | ndtr0 = NDTR0_tCH(ns2cycle(t->tCH, nand_clk)) | | ||
| 321 | NDTR0_tCS(ns2cycle(t->tCS, nand_clk)) | | ||
| 322 | NDTR0_tWH(ns2cycle(t->tWH, nand_clk)) | | ||
| 323 | NDTR0_tWP(ns2cycle(t->tWP, nand_clk)) | | ||
| 324 | NDTR0_tRH(ns2cycle(t->tRH, nand_clk)) | | ||
| 325 | NDTR0_tRP(ns2cycle(t->tRP, nand_clk)); | ||
| 326 | |||
| 327 | ndtr1 = NDTR1_tR(ns2cycle(t->tR, nand_clk)) | | ||
| 328 | NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | | ||
| 329 | NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); | ||
| 330 | |||
| 331 | nand_writel(info, NDTR0CS0, ndtr0); | ||
| 332 | nand_writel(info, NDTR1CS0, ndtr1); | ||
| 333 | } | ||
| 334 | |||
| 335 | #define WAIT_EVENT_TIMEOUT 10 | ||
| 336 | |||
| 337 | static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event) | ||
| 338 | { | ||
| 339 | int timeout = WAIT_EVENT_TIMEOUT; | ||
| 340 | uint32_t ndsr; | ||
| 341 | |||
| 342 | while (timeout--) { | ||
| 343 | ndsr = nand_readl(info, NDSR) & NDSR_MASK; | ||
| 344 | if (ndsr & event) { | ||
| 345 | nand_writel(info, NDSR, ndsr); | ||
| 346 | return 0; | ||
| 347 | } | ||
| 348 | udelay(10); | ||
| 349 | } | ||
| 350 | |||
| 351 | return -ETIMEDOUT; | ||
| 352 | } | ||
| 353 | |||
| 354 | static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, | ||
| 355 | uint16_t cmd, int column, int page_addr) | ||
| 356 | { | ||
| 357 | struct pxa3xx_nand_flash *f = info->flash_info; | ||
| 358 | struct pxa3xx_nand_cmdset *cmdset = f->cmdset; | ||
| 359 | |||
| 360 | /* calculate data size */ | ||
| 361 | switch (f->page_size) { | ||
| 362 | case 2048: | ||
| 363 | info->data_size = (info->use_ecc) ? 2088 : 2112; | ||
| 364 | break; | ||
| 365 | case 512: | ||
| 366 | info->data_size = (info->use_ecc) ? 520 : 528; | ||
| 367 | break; | ||
| 368 | default: | ||
| 369 | return -EINVAL; | ||
| 370 | } | ||
| 371 | |||
| 372 | /* generate values for NDCBx registers */ | ||
| 373 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); | ||
| 374 | info->ndcb1 = 0; | ||
| 375 | info->ndcb2 = 0; | ||
| 376 | info->ndcb0 |= NDCB0_ADDR_CYC(f->row_addr_cycles + f->col_addr_cycles); | ||
| 377 | |||
| 378 | if (f->col_addr_cycles == 2) { | ||
| 379 | /* large block, 2 cycles for column address | ||
| 380 | * row address starts from 3rd cycle | ||
| 381 | */ | ||
| 382 | info->ndcb1 |= (page_addr << 16) | (column & 0xffff); | ||
| 383 | if (f->row_addr_cycles == 3) | ||
| 384 | info->ndcb2 = (page_addr >> 16) & 0xff; | ||
| 385 | } else | ||
| 386 | /* small block, 1 cycles for column address | ||
| 387 | * row address starts from 2nd cycle | ||
| 388 | */ | ||
| 389 | info->ndcb1 = (page_addr << 8) | (column & 0xff); | ||
| 390 | |||
| 391 | if (cmd == cmdset->program) | ||
| 392 | info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS; | ||
| 393 | |||
| 394 | return 0; | ||
| 395 | } | ||
| 396 | |||
| 397 | static int prepare_erase_cmd(struct pxa3xx_nand_info *info, | ||
| 398 | uint16_t cmd, int page_addr) | ||
| 399 | { | ||
| 400 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); | ||
| 401 | info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3); | ||
| 402 | info->ndcb1 = page_addr; | ||
| 403 | info->ndcb2 = 0; | ||
| 404 | return 0; | ||
| 405 | } | ||
| 406 | |||
| 407 | static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) | ||
| 408 | { | ||
| 409 | struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset; | ||
| 410 | |||
| 411 | info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); | ||
| 412 | info->ndcb1 = 0; | ||
| 413 | info->ndcb2 = 0; | ||
| 414 | |||
| 415 | if (cmd == cmdset->read_id) { | ||
| 416 | info->ndcb0 |= NDCB0_CMD_TYPE(3); | ||
| 417 | info->data_size = 8; | ||
| 418 | } else if (cmd == cmdset->read_status) { | ||
| 419 | info->ndcb0 |= NDCB0_CMD_TYPE(4); | ||
| 420 | info->data_size = 8; | ||
| 421 | } else if (cmd == cmdset->reset || cmd == cmdset->lock || | ||
| 422 | cmd == cmdset->unlock) { | ||
| 423 | info->ndcb0 |= NDCB0_CMD_TYPE(5); | ||
| 424 | } else | ||
| 425 | return -EINVAL; | ||
| 426 | |||
| 427 | return 0; | ||
| 428 | } | ||
| 429 | |||
| 430 | static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) | ||
| 431 | { | ||
| 432 | uint32_t ndcr; | ||
| 433 | |||
| 434 | ndcr = nand_readl(info, NDCR); | ||
| 435 | nand_writel(info, NDCR, ndcr & ~int_mask); | ||
| 436 | } | ||
| 437 | |||
| 438 | static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) | ||
| 439 | { | ||
| 440 | uint32_t ndcr; | ||
| 441 | |||
| 442 | ndcr = nand_readl(info, NDCR); | ||
| 443 | nand_writel(info, NDCR, ndcr | int_mask); | ||
| 444 | } | ||
| 445 | |||
| 446 | /* NOTE: it is a must to set ND_RUN firstly, then write command buffer | ||
| 447 | * otherwise, it does not work | ||
| 448 | */ | ||
| 449 | static int write_cmd(struct pxa3xx_nand_info *info) | ||
| 450 | { | ||
| 451 | uint32_t ndcr; | ||
| 452 | |||
| 453 | /* clear status bits and run */ | ||
| 454 | nand_writel(info, NDSR, NDSR_MASK); | ||
| 455 | |||
| 456 | ndcr = info->reg_ndcr; | ||
| 457 | |||
| 458 | ndcr |= info->use_ecc ? NDCR_ECC_EN : 0; | ||
| 459 | ndcr |= info->use_dma ? NDCR_DMA_EN : 0; | ||
| 460 | ndcr |= NDCR_ND_RUN; | ||
| 461 | |||
| 462 | nand_writel(info, NDCR, ndcr); | ||
| 463 | |||
| 464 | if (wait_for_event(info, NDSR_WRCMDREQ)) { | ||
| 465 | printk(KERN_ERR "timed out writing command\n"); | ||
| 466 | return -ETIMEDOUT; | ||
| 467 | } | ||
| 468 | |||
| 469 | nand_writel(info, NDCB0, info->ndcb0); | ||
| 470 | nand_writel(info, NDCB0, info->ndcb1); | ||
| 471 | nand_writel(info, NDCB0, info->ndcb2); | ||
| 472 | return 0; | ||
| 473 | } | ||
| 474 | |||
| 475 | static int handle_data_pio(struct pxa3xx_nand_info *info) | ||
| 476 | { | ||
| 477 | int ret, timeout = CHIP_DELAY_TIMEOUT; | ||
| 478 | |||
| 479 | switch (info->state) { | ||
| 480 | case STATE_PIO_WRITING: | ||
| 481 | __raw_writesl(info->mmio_base + NDDB, info->data_buff, | ||
| 482 | info->data_size << 2); | ||
| 483 | |||
| 484 | enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); | ||
| 485 | |||
| 486 | ret = wait_for_completion_timeout(&info->cmd_complete, timeout); | ||
| 487 | if (!ret) { | ||
| 488 | printk(KERN_ERR "program command time out\n"); | ||
| 489 | return -1; | ||
| 490 | } | ||
| 491 | break; | ||
| 492 | case STATE_PIO_READING: | ||
| 493 | __raw_readsl(info->mmio_base + NDDB, info->data_buff, | ||
| 494 | info->data_size << 2); | ||
| 495 | break; | ||
| 496 | default: | ||
| 497 | printk(KERN_ERR "%s: invalid state %d\n", __func__, | ||
| 498 | info->state); | ||
| 499 | return -EINVAL; | ||
| 500 | } | ||
| 501 | |||
| 502 | info->state = STATE_READY; | ||
| 503 | return 0; | ||
| 504 | } | ||
| 505 | |||
| 506 | static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) | ||
| 507 | { | ||
| 508 | struct pxa_dma_desc *desc = info->data_desc; | ||
| 509 | int dma_len = ALIGN(info->data_size, 32); | ||
| 510 | |||
| 511 | desc->ddadr = DDADR_STOP; | ||
| 512 | desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len; | ||
| 513 | |||
| 514 | if (dir_out) { | ||
| 515 | desc->dsadr = info->data_buff_phys; | ||
| 516 | desc->dtadr = NDDB_DMA_ADDR; | ||
| 517 | desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG; | ||
| 518 | } else { | ||
| 519 | desc->dtadr = info->data_buff_phys; | ||
| 520 | desc->dsadr = NDDB_DMA_ADDR; | ||
| 521 | desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; | ||
| 522 | } | ||
| 523 | |||
| 524 | DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch; | ||
| 525 | DDADR(info->data_dma_ch) = info->data_desc_addr; | ||
| 526 | DCSR(info->data_dma_ch) |= DCSR_RUN; | ||
| 527 | } | ||
| 528 | |||
| 529 | static void pxa3xx_nand_data_dma_irq(int channel, void *data) | ||
| 530 | { | ||
| 531 | struct pxa3xx_nand_info *info = data; | ||
| 532 | uint32_t dcsr; | ||
| 533 | |||
| 534 | dcsr = DCSR(channel); | ||
| 535 | DCSR(channel) = dcsr; | ||
| 536 | |||
| 537 | if (dcsr & DCSR_BUSERR) { | ||
| 538 | info->retcode = ERR_DMABUSERR; | ||
| 539 | complete(&info->cmd_complete); | ||
| 540 | } | ||
| 541 | |||
| 542 | if (info->state == STATE_DMA_WRITING) { | ||
| 543 | info->state = STATE_DMA_DONE; | ||
| 544 | enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); | ||
| 545 | } else { | ||
| 546 | info->state = STATE_READY; | ||
| 547 | complete(&info->cmd_complete); | ||
| 548 | } | ||
| 549 | } | ||
| 550 | |||
| 551 | static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) | ||
| 552 | { | ||
| 553 | struct pxa3xx_nand_info *info = devid; | ||
| 554 | unsigned int status; | ||
| 555 | |||
| 556 | status = nand_readl(info, NDSR); | ||
| 557 | |||
| 558 | if (status & (NDSR_RDDREQ | NDSR_DBERR)) { | ||
| 559 | if (status & NDSR_DBERR) | ||
| 560 | info->retcode = ERR_DBERR; | ||
| 561 | |||
| 562 | disable_int(info, NDSR_RDDREQ | NDSR_DBERR); | ||
| 563 | |||
| 564 | if (info->use_dma) { | ||
| 565 | info->state = STATE_DMA_READING; | ||
| 566 | start_data_dma(info, 0); | ||
| 567 | } else { | ||
| 568 | info->state = STATE_PIO_READING; | ||
| 569 | complete(&info->cmd_complete); | ||
| 570 | } | ||
| 571 | } else if (status & NDSR_WRDREQ) { | ||
| 572 | disable_int(info, NDSR_WRDREQ); | ||
| 573 | if (info->use_dma) { | ||
| 574 | info->state = STATE_DMA_WRITING; | ||
| 575 | start_data_dma(info, 1); | ||
| 576 | } else { | ||
| 577 | info->state = STATE_PIO_WRITING; | ||
| 578 | complete(&info->cmd_complete); | ||
| 579 | } | ||
| 580 | } else if (status & (NDSR_CS0_BBD | NDSR_CS0_CMDD)) { | ||
| 581 | if (status & NDSR_CS0_BBD) | ||
| 582 | info->retcode = ERR_BBERR; | ||
| 583 | |||
| 584 | disable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); | ||
| 585 | info->state = STATE_READY; | ||
| 586 | complete(&info->cmd_complete); | ||
| 587 | } | ||
| 588 | nand_writel(info, NDSR, status); | ||
| 589 | return IRQ_HANDLED; | ||
| 590 | } | ||
| 591 | |||
| 592 | static int pxa3xx_nand_do_cmd(struct pxa3xx_nand_info *info, uint32_t event) | ||
| 593 | { | ||
| 594 | uint32_t ndcr; | ||
| 595 | int ret, timeout = CHIP_DELAY_TIMEOUT; | ||
| 596 | |||
| 597 | if (write_cmd(info)) { | ||
| 598 | info->retcode = ERR_SENDCMD; | ||
| 599 | goto fail_stop; | ||
| 600 | } | ||
| 601 | |||
| 602 | info->state = STATE_CMD_HANDLE; | ||
| 603 | |||
| 604 | enable_int(info, event); | ||
| 605 | |||
| 606 | ret = wait_for_completion_timeout(&info->cmd_complete, timeout); | ||
| 607 | if (!ret) { | ||
| 608 | printk(KERN_ERR "command execution timed out\n"); | ||
| 609 | info->retcode = ERR_SENDCMD; | ||
| 610 | goto fail_stop; | ||
| 611 | } | ||
| 612 | |||
| 613 | if (info->use_dma == 0 && info->data_size > 0) | ||
| 614 | if (handle_data_pio(info)) | ||
| 615 | goto fail_stop; | ||
| 616 | |||
| 617 | return 0; | ||
| 618 | |||
| 619 | fail_stop: | ||
| 620 | ndcr = nand_readl(info, NDCR); | ||
| 621 | nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN); | ||
| 622 | udelay(10); | ||
| 623 | return -ETIMEDOUT; | ||
| 624 | } | ||
| 625 | |||
| 626 | static int pxa3xx_nand_dev_ready(struct mtd_info *mtd) | ||
| 627 | { | ||
| 628 | struct pxa3xx_nand_info *info = mtd->priv; | ||
| 629 | return (nand_readl(info, NDSR) & NDSR_RDY) ? 1 : 0; | ||
| 630 | } | ||
| 631 | |||
| 632 | static inline int is_buf_blank(uint8_t *buf, size_t len) | ||
| 633 | { | ||
| 634 | for (; len > 0; len--) | ||
| 635 | if (*buf++ != 0xff) | ||
| 636 | return 0; | ||
| 637 | return 1; | ||
| 638 | } | ||
| 639 | |||
| 640 | static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, | ||
| 641 | int column, int page_addr) | ||
| 642 | { | ||
| 643 | struct pxa3xx_nand_info *info = mtd->priv; | ||
| 644 | struct pxa3xx_nand_flash *flash_info = info->flash_info; | ||
| 645 | struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset; | ||
| 646 | int ret; | ||
| 647 | |||
| 648 | info->use_dma = (use_dma) ? 1 : 0; | ||
| 649 | info->use_ecc = 0; | ||
| 650 | info->data_size = 0; | ||
| 651 | info->state = STATE_READY; | ||
| 652 | |||
| 653 | init_completion(&info->cmd_complete); | ||
| 654 | |||
| 655 | switch (command) { | ||
| 656 | case NAND_CMD_READOOB: | ||
| 657 | /* disable HW ECC to get all the OOB data */ | ||
| 658 | info->buf_count = mtd->writesize + mtd->oobsize; | ||
| 659 | info->buf_start = mtd->writesize + column; | ||
| 660 | |||
| 661 | if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) | ||
| 662 | break; | ||
| 663 | |||
| 664 | pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR); | ||
| 665 | |||
| 666 | /* We only are OOB, so if the data has error, does not matter */ | ||
| 667 | if (info->retcode == ERR_DBERR) | ||
| 668 | info->retcode = ERR_NONE; | ||
| 669 | break; | ||
| 670 | |||
| 671 | case NAND_CMD_READ0: | ||
| 672 | info->use_ecc = 1; | ||
| 673 | info->retcode = ERR_NONE; | ||
| 674 | info->buf_start = column; | ||
| 675 | info->buf_count = mtd->writesize + mtd->oobsize; | ||
| 676 | memset(info->data_buff, 0xFF, info->buf_count); | ||
| 677 | |||
| 678 | if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) | ||
| 679 | break; | ||
| 680 | |||
| 681 | pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR); | ||
| 682 | |||
| 683 | if (info->retcode == ERR_DBERR) { | ||
| 684 | /* for blank page (all 0xff), HW will calculate its ECC as | ||
| 685 | * 0, which is different from the ECC information within | ||
| 686 | * OOB, ignore such double bit errors | ||
| 687 | */ | ||
| 688 | if (is_buf_blank(info->data_buff, mtd->writesize)) | ||
| 689 | info->retcode = ERR_NONE; | ||
| 690 | } | ||
| 691 | break; | ||
| 692 | case NAND_CMD_SEQIN: | ||
| 693 | info->buf_start = column; | ||
| 694 | info->buf_count = mtd->writesize + mtd->oobsize; | ||
| 695 | memset(info->data_buff, 0xff, info->buf_count); | ||
| 696 | |||
| 697 | /* save column/page_addr for next CMD_PAGEPROG */ | ||
| 698 | info->seqin_column = column; | ||
| 699 | info->seqin_page_addr = page_addr; | ||
| 700 | break; | ||
| 701 | case NAND_CMD_PAGEPROG: | ||
| 702 | info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1; | ||
| 703 | |||
| 704 | if (prepare_read_prog_cmd(info, cmdset->program, | ||
| 705 | info->seqin_column, info->seqin_page_addr)) | ||
| 706 | break; | ||
| 707 | |||
| 708 | pxa3xx_nand_do_cmd(info, NDSR_WRDREQ); | ||
| 709 | break; | ||
| 710 | case NAND_CMD_ERASE1: | ||
| 711 | if (prepare_erase_cmd(info, cmdset->erase, page_addr)) | ||
| 712 | break; | ||
| 713 | |||
| 714 | pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); | ||
| 715 | break; | ||
| 716 | case NAND_CMD_ERASE2: | ||
| 717 | break; | ||
| 718 | case NAND_CMD_READID: | ||
| 719 | case NAND_CMD_STATUS: | ||
| 720 | info->use_dma = 0; /* force PIO read */ | ||
| 721 | info->buf_start = 0; | ||
| 722 | info->buf_count = (command == NAND_CMD_READID) ? | ||
| 723 | flash_info->read_id_bytes : 1; | ||
| 724 | |||
| 725 | if (prepare_other_cmd(info, (command == NAND_CMD_READID) ? | ||
| 726 | cmdset->read_id : cmdset->read_status)) | ||
| 727 | break; | ||
| 728 | |||
| 729 | pxa3xx_nand_do_cmd(info, NDSR_RDDREQ); | ||
| 730 | break; | ||
| 731 | case NAND_CMD_RESET: | ||
| 732 | if (prepare_other_cmd(info, cmdset->reset)) | ||
| 733 | break; | ||
| 734 | |||
| 735 | ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD); | ||
| 736 | if (ret == 0) { | ||
| 737 | int timeout = 2; | ||
| 738 | uint32_t ndcr; | ||
| 739 | |||
| 740 | while (timeout--) { | ||
| 741 | if (nand_readl(info, NDSR) & NDSR_RDY) | ||
| 742 | break; | ||
| 743 | msleep(10); | ||
| 744 | } | ||
| 745 | |||
| 746 | ndcr = nand_readl(info, NDCR); | ||
| 747 | nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN); | ||
| 748 | } | ||
| 749 | break; | ||
| 750 | default: | ||
| 751 | printk(KERN_ERR "non-supported command.\n"); | ||
| 752 | break; | ||
| 753 | } | ||
| 754 | |||
| 755 | if (info->retcode == ERR_DBERR) { | ||
| 756 | printk(KERN_ERR "double bit error @ page %08x\n", page_addr); | ||
| 757 | info->retcode = ERR_NONE; | ||
| 758 | } | ||
| 759 | } | ||
| 760 | |||
| 761 | static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd) | ||
| 762 | { | ||
| 763 | struct pxa3xx_nand_info *info = mtd->priv; | ||
| 764 | char retval = 0xFF; | ||
| 765 | |||
| 766 | if (info->buf_start < info->buf_count) | ||
| 767 | /* Has just send a new command? */ | ||
| 768 | retval = info->data_buff[info->buf_start++]; | ||
| 769 | |||
| 770 | return retval; | ||
| 771 | } | ||
| 772 | |||
| 773 | static u16 pxa3xx_nand_read_word(struct mtd_info *mtd) | ||
| 774 | { | ||
| 775 | struct pxa3xx_nand_info *info = mtd->priv; | ||
| 776 | u16 retval = 0xFFFF; | ||
| 777 | |||
| 778 | if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) { | ||
| 779 | retval = *((u16 *)(info->data_buff+info->buf_start)); | ||
| 780 | info->buf_start += 2; | ||
| 781 | } | ||
| 782 | return retval; | ||
| 783 | } | ||
| 784 | |||
| 785 | static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len) | ||
| 786 | { | ||
| 787 | struct pxa3xx_nand_info *info = mtd->priv; | ||
| 788 | int real_len = min_t(size_t, len, info->buf_count - info->buf_start); | ||
| 789 | |||
| 790 | memcpy(buf, info->data_buff + info->buf_start, real_len); | ||
| 791 | info->buf_start += real_len; | ||
| 792 | } | ||
| 793 | |||
| 794 | static void pxa3xx_nand_write_buf(struct mtd_info *mtd, | ||
| 795 | const uint8_t *buf, int len) | ||
| 796 | { | ||
| 797 | struct pxa3xx_nand_info *info = mtd->priv; | ||
| 798 | int real_len = min_t(size_t, len, info->buf_count - info->buf_start); | ||
| 799 | |||
| 800 | memcpy(info->data_buff + info->buf_start, buf, real_len); | ||
| 801 | info->buf_start += real_len; | ||
| 802 | } | ||
| 803 | |||
| 804 | static int pxa3xx_nand_verify_buf(struct mtd_info *mtd, | ||
| 805 | const uint8_t *buf, int len) | ||
| 806 | { | ||
| 807 | return 0; | ||
| 808 | } | ||
| 809 | |||
| 810 | static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip) | ||
| 811 | { | ||
| 812 | return; | ||
| 813 | } | ||
| 814 | |||
| 815 | static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) | ||
| 816 | { | ||
| 817 | struct pxa3xx_nand_info *info = mtd->priv; | ||
| 818 | |||
| 819 | /* pxa3xx_nand_send_command has waited for command complete */ | ||
| 820 | if (this->state == FL_WRITING || this->state == FL_ERASING) { | ||
| 821 | if (info->retcode == ERR_NONE) | ||
| 822 | return 0; | ||
| 823 | else { | ||
| 824 | /* | ||
| 825 | * any error make it return 0x01 which will tell | ||
| 826 | * the caller the erase and write fail | ||
| 827 | */ | ||
| 828 | return 0x01; | ||
| 829 | } | ||
| 830 | } | ||
| 831 | |||
| 832 | return 0; | ||
| 833 | } | ||
| 834 | |||
| 835 | static void pxa3xx_nand_ecc_hwctl(struct mtd_info *mtd, int mode) | ||
| 836 | { | ||
| 837 | return; | ||
| 838 | } | ||
| 839 | |||
| 840 | static int pxa3xx_nand_ecc_calculate(struct mtd_info *mtd, | ||
| 841 | const uint8_t *dat, uint8_t *ecc_code) | ||
| 842 | { | ||
| 843 | return 0; | ||
| 844 | } | ||
| 845 | |||
| 846 | static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd, | ||
| 847 | uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc) | ||
| 848 | { | ||
| 849 | struct pxa3xx_nand_info *info = mtd->priv; | ||
| 850 | /* | ||
| 851 | * Any error include ERR_SEND_CMD, ERR_DBERR, ERR_BUSERR, we | ||
| 852 | * consider it as a ecc error which will tell the caller the | ||
| 853 | * read fail We have distinguish all the errors, but the | ||
| 854 | * nand_read_ecc only check this function return value | ||
| 855 | */ | ||
| 856 | if (info->retcode != ERR_NONE) | ||
| 857 | return -1; | ||
| 858 | |||
| 859 | return 0; | ||
| 860 | } | ||
| 861 | |||
| 862 | static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) | ||
| 863 | { | ||
| 864 | struct pxa3xx_nand_flash *f = info->flash_info; | ||
| 865 | struct pxa3xx_nand_cmdset *cmdset = f->cmdset; | ||
| 866 | uint32_t ndcr; | ||
| 867 | uint8_t id_buff[8]; | ||
| 868 | |||
| 869 | if (prepare_other_cmd(info, cmdset->read_id)) { | ||
| 870 | printk(KERN_ERR "failed to prepare command\n"); | ||
| 871 | return -EINVAL; | ||
| 872 | } | ||
| 873 | |||
| 874 | /* Send command */ | ||
| 875 | if (write_cmd(info)) | ||
| 876 | goto fail_timeout; | ||
| 877 | |||
| 878 | /* Wait for CMDDM(command done successfully) */ | ||
| 879 | if (wait_for_event(info, NDSR_RDDREQ)) | ||
| 880 | goto fail_timeout; | ||
| 881 | |||
| 882 | __raw_readsl(info->mmio_base + NDDB, id_buff, 2); | ||
| 883 | *id = id_buff[0] | (id_buff[1] << 8); | ||
| 884 | return 0; | ||
| 885 | |||
| 886 | fail_timeout: | ||
| 887 | ndcr = nand_readl(info, NDCR); | ||
| 888 | nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN); | ||
| 889 | udelay(10); | ||
| 890 | return -ETIMEDOUT; | ||
| 891 | } | ||
| 892 | |||
| 893 | static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, | ||
| 894 | struct pxa3xx_nand_flash *f) | ||
| 895 | { | ||
| 896 | struct platform_device *pdev = info->pdev; | ||
| 897 | struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; | ||
| 898 | uint32_t ndcr = 0x00000FFF; /* disable all interrupts */ | ||
| 899 | |||
| 900 | if (f->page_size != 2048 && f->page_size != 512) | ||
| 901 | return -EINVAL; | ||
| 902 | |||
| 903 | if (f->flash_width != 16 && f->flash_width != 8) | ||
| 904 | return -EINVAL; | ||
| 905 | |||
| 906 | /* calculate flash information */ | ||
| 907 | f->oob_size = (f->page_size == 2048) ? 64 : 16; | ||
| 908 | f->read_id_bytes = (f->page_size == 2048) ? 4 : 2; | ||
| 909 | |||
| 910 | /* calculate addressing information */ | ||
| 911 | f->col_addr_cycles = (f->page_size == 2048) ? 2 : 1; | ||
| 912 | |||
| 913 | if (f->num_blocks * f->page_per_block > 65536) | ||
| 914 | f->row_addr_cycles = 3; | ||
| 915 | else | ||
| 916 | f->row_addr_cycles = 2; | ||
| 917 | |||
| 918 | ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0; | ||
| 919 | ndcr |= (f->col_addr_cycles == 2) ? NDCR_RA_START : 0; | ||
| 920 | ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0; | ||
| 921 | ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0; | ||
| 922 | ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0; | ||
| 923 | ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0; | ||
| 924 | |||
| 925 | ndcr |= NDCR_RD_ID_CNT(f->read_id_bytes); | ||
| 926 | ndcr |= NDCR_SPARE_EN; /* enable spare by default */ | ||
| 927 | |||
| 928 | info->reg_ndcr = ndcr; | ||
| 929 | |||
| 930 | pxa3xx_nand_set_timing(info, f->timing); | ||
| 931 | info->flash_info = f; | ||
| 932 | return 0; | ||
| 933 | } | ||
| 934 | |||
| 935 | static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info) | ||
| 936 | { | ||
| 937 | struct pxa3xx_nand_flash *f; | ||
| 938 | uint32_t id; | ||
| 939 | int i; | ||
| 940 | |||
| 941 | for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) { | ||
| 942 | |||
| 943 | f = builtin_flash_types[i]; | ||
| 944 | |||
| 945 | if (pxa3xx_nand_config_flash(info, f)) | ||
| 946 | continue; | ||
| 947 | |||
| 948 | if (__readid(info, &id)) | ||
| 949 | continue; | ||
| 950 | |||
| 951 | if (id == f->chip_id) | ||
| 952 | return 0; | ||
| 953 | } | ||
| 954 | |||
| 955 | return -ENODEV; | ||
| 956 | } | ||
| 957 | |||
| 958 | /* the maximum possible buffer size for large page with OOB data | ||
| 959 | * is: 2048 + 64 = 2112 bytes, allocate a page here for both the | ||
| 960 | * data buffer and the DMA descriptor | ||
| 961 | */ | ||
| 962 | #define MAX_BUFF_SIZE PAGE_SIZE | ||
| 963 | |||
| 964 | static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) | ||
| 965 | { | ||
| 966 | struct platform_device *pdev = info->pdev; | ||
| 967 | int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc); | ||
| 968 | |||
| 969 | if (use_dma == 0) { | ||
| 970 | info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL); | ||
| 971 | if (info->data_buff == NULL) | ||
| 972 | return -ENOMEM; | ||
| 973 | return 0; | ||
| 974 | } | ||
| 975 | |||
| 976 | info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE, | ||
| 977 | &info->data_buff_phys, GFP_KERNEL); | ||
| 978 | if (info->data_buff == NULL) { | ||
| 979 | dev_err(&pdev->dev, "failed to allocate dma buffer\n"); | ||
| 980 | return -ENOMEM; | ||
| 981 | } | ||
| 982 | |||
| 983 | info->data_buff_size = MAX_BUFF_SIZE; | ||
| 984 | info->data_desc = (void *)info->data_buff + data_desc_offset; | ||
| 985 | info->data_desc_addr = info->data_buff_phys + data_desc_offset; | ||
| 986 | |||
| 987 | info->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW, | ||
| 988 | pxa3xx_nand_data_dma_irq, info); | ||
| 989 | if (info->data_dma_ch < 0) { | ||
| 990 | dev_err(&pdev->dev, "failed to request data dma\n"); | ||
| 991 | dma_free_coherent(&pdev->dev, info->data_buff_size, | ||
| 992 | info->data_buff, info->data_buff_phys); | ||
| 993 | return info->data_dma_ch; | ||
| 994 | } | ||
| 995 | |||
| 996 | return 0; | ||
| 997 | } | ||
| 998 | |||
| 999 | static struct nand_ecclayout hw_smallpage_ecclayout = { | ||
| 1000 | .eccbytes = 6, | ||
| 1001 | .eccpos = {8, 9, 10, 11, 12, 13 }, | ||
| 1002 | .oobfree = { {2, 6} } | ||
| 1003 | }; | ||
| 1004 | |||
| 1005 | static struct nand_ecclayout hw_largepage_ecclayout = { | ||
| 1006 | .eccbytes = 24, | ||
| 1007 | .eccpos = { | ||
| 1008 | 40, 41, 42, 43, 44, 45, 46, 47, | ||
| 1009 | 48, 49, 50, 51, 52, 53, 54, 55, | ||
| 1010 | 56, 57, 58, 59, 60, 61, 62, 63}, | ||
| 1011 | .oobfree = { {2, 38} } | ||
| 1012 | }; | ||
| 1013 | |||
| 1014 | static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, | ||
| 1015 | struct pxa3xx_nand_info *info) | ||
| 1016 | { | ||
| 1017 | struct pxa3xx_nand_flash *f = info->flash_info; | ||
| 1018 | struct nand_chip *this = &info->nand_chip; | ||
| 1019 | |||
| 1020 | this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0; | ||
| 1021 | |||
| 1022 | this->waitfunc = pxa3xx_nand_waitfunc; | ||
| 1023 | this->select_chip = pxa3xx_nand_select_chip; | ||
| 1024 | this->dev_ready = pxa3xx_nand_dev_ready; | ||
| 1025 | this->cmdfunc = pxa3xx_nand_cmdfunc; | ||
| 1026 | this->read_word = pxa3xx_nand_read_word; | ||
| 1027 | this->read_byte = pxa3xx_nand_read_byte; | ||
| 1028 | this->read_buf = pxa3xx_nand_read_buf; | ||
| 1029 | this->write_buf = pxa3xx_nand_write_buf; | ||
| 1030 | this->verify_buf = pxa3xx_nand_verify_buf; | ||
| 1031 | |||
| 1032 | this->ecc.mode = NAND_ECC_HW; | ||
| 1033 | this->ecc.hwctl = pxa3xx_nand_ecc_hwctl; | ||
| 1034 | this->ecc.calculate = pxa3xx_nand_ecc_calculate; | ||
| 1035 | this->ecc.correct = pxa3xx_nand_ecc_correct; | ||
| 1036 | this->ecc.size = f->page_size; | ||
| 1037 | |||
| 1038 | if (f->page_size == 2048) | ||
| 1039 | this->ecc.layout = &hw_largepage_ecclayout; | ||
| 1040 | else | ||
| 1041 | this->ecc.layout = &hw_smallpage_ecclayout; | ||
| 1042 | |||
| 1043 | this->chip_delay = 25; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | static int pxa3xx_nand_probe(struct platform_device *pdev) | ||
| 1047 | { | ||
| 1048 | struct pxa3xx_nand_platform_data *pdata; | ||
| 1049 | struct pxa3xx_nand_info *info; | ||
| 1050 | struct nand_chip *this; | ||
| 1051 | struct mtd_info *mtd; | ||
| 1052 | struct resource *r; | ||
| 1053 | int ret = 0, irq; | ||
| 1054 | |||
| 1055 | pdata = pdev->dev.platform_data; | ||
| 1056 | |||
| 1057 | if (!pdata) { | ||
| 1058 | dev_err(&pdev->dev, "no platform data defined\n"); | ||
| 1059 | return -ENODEV; | ||
| 1060 | } | ||
| 1061 | |||
| 1062 | mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info), | ||
| 1063 | GFP_KERNEL); | ||
| 1064 | if (!mtd) { | ||
| 1065 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
| 1066 | return -ENOMEM; | ||
| 1067 | } | ||
| 1068 | |||
| 1069 | info = (struct pxa3xx_nand_info *)(&mtd[1]); | ||
| 1070 | info->pdev = pdev; | ||
| 1071 | |||
| 1072 | this = &info->nand_chip; | ||
| 1073 | mtd->priv = info; | ||
| 1074 | |||
| 1075 | info->clk = clk_get(&pdev->dev, "NANDCLK"); | ||
| 1076 | if (IS_ERR(info->clk)) { | ||
| 1077 | dev_err(&pdev->dev, "failed to get nand clock\n"); | ||
| 1078 | ret = PTR_ERR(info->clk); | ||
| 1079 | goto fail_free_mtd; | ||
| 1080 | } | ||
| 1081 | clk_enable(info->clk); | ||
| 1082 | |||
| 1083 | r = platform_get_resource(pdev, IORESOURCE_DMA, 0); | ||
| 1084 | if (r == NULL) { | ||
| 1085 | dev_err(&pdev->dev, "no resource defined for data DMA\n"); | ||
| 1086 | ret = -ENXIO; | ||
| 1087 | goto fail_put_clk; | ||
| 1088 | } | ||
| 1089 | info->drcmr_dat = r->start; | ||
| 1090 | |||
| 1091 | r = platform_get_resource(pdev, IORESOURCE_DMA, 1); | ||
| 1092 | if (r == NULL) { | ||
| 1093 | dev_err(&pdev->dev, "no resource defined for command DMA\n"); | ||
| 1094 | ret = -ENXIO; | ||
| 1095 | goto fail_put_clk; | ||
| 1096 | } | ||
| 1097 | info->drcmr_cmd = r->start; | ||
| 1098 | |||
| 1099 | irq = platform_get_irq(pdev, 0); | ||
| 1100 | if (irq < 0) { | ||
| 1101 | dev_err(&pdev->dev, "no IRQ resource defined\n"); | ||
| 1102 | ret = -ENXIO; | ||
| 1103 | goto fail_put_clk; | ||
| 1104 | } | ||
| 1105 | |||
| 1106 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 1107 | if (r == NULL) { | ||
| 1108 | dev_err(&pdev->dev, "no IO memory resource defined\n"); | ||
| 1109 | ret = -ENODEV; | ||
| 1110 | goto fail_put_clk; | ||
| 1111 | } | ||
| 1112 | |||
| 1113 | r = request_mem_region(r->start, r->end - r->start + 1, pdev->name); | ||
| 1114 | if (r == NULL) { | ||
| 1115 | dev_err(&pdev->dev, "failed to request memory resource\n"); | ||
| 1116 | ret = -EBUSY; | ||
| 1117 | goto fail_put_clk; | ||
| 1118 | } | ||
| 1119 | |||
| 1120 | info->mmio_base = ioremap(r->start, r->end - r->start + 1); | ||
| 1121 | if (info->mmio_base == NULL) { | ||
| 1122 | dev_err(&pdev->dev, "ioremap() failed\n"); | ||
| 1123 | ret = -ENODEV; | ||
| 1124 | goto fail_free_res; | ||
| 1125 | } | ||
| 1126 | |||
| 1127 | ret = pxa3xx_nand_init_buff(info); | ||
| 1128 | if (ret) | ||
| 1129 | goto fail_free_io; | ||
| 1130 | |||
| 1131 | ret = request_irq(IRQ_NAND, pxa3xx_nand_irq, IRQF_DISABLED, | ||
| 1132 | pdev->name, info); | ||
| 1133 | if (ret < 0) { | ||
| 1134 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
| 1135 | goto fail_free_buf; | ||
| 1136 | } | ||
| 1137 | |||
| 1138 | ret = pxa3xx_nand_detect_flash(info); | ||
| 1139 | if (ret) { | ||
| 1140 | dev_err(&pdev->dev, "failed to detect flash\n"); | ||
| 1141 | ret = -ENODEV; | ||
| 1142 | goto fail_free_irq; | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | pxa3xx_nand_init_mtd(mtd, info); | ||
| 1146 | |||
| 1147 | platform_set_drvdata(pdev, mtd); | ||
| 1148 | |||
| 1149 | if (nand_scan(mtd, 1)) { | ||
| 1150 | dev_err(&pdev->dev, "failed to scan nand\n"); | ||
| 1151 | ret = -ENXIO; | ||
| 1152 | goto fail_free_irq; | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); | ||
| 1156 | |||
| 1157 | fail_free_irq: | ||
| 1158 | free_irq(IRQ_NAND, info); | ||
| 1159 | fail_free_buf: | ||
| 1160 | if (use_dma) { | ||
| 1161 | pxa_free_dma(info->data_dma_ch); | ||
| 1162 | dma_free_coherent(&pdev->dev, info->data_buff_size, | ||
| 1163 | info->data_buff, info->data_buff_phys); | ||
| 1164 | } else | ||
| 1165 | kfree(info->data_buff); | ||
| 1166 | fail_free_io: | ||
| 1167 | iounmap(info->mmio_base); | ||
| 1168 | fail_free_res: | ||
| 1169 | release_mem_region(r->start, r->end - r->start + 1); | ||
| 1170 | fail_put_clk: | ||
| 1171 | clk_disable(info->clk); | ||
| 1172 | clk_put(info->clk); | ||
| 1173 | fail_free_mtd: | ||
| 1174 | kfree(mtd); | ||
| 1175 | return ret; | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | static int pxa3xx_nand_remove(struct platform_device *pdev) | ||
| 1179 | { | ||
| 1180 | struct mtd_info *mtd = platform_get_drvdata(pdev); | ||
| 1181 | struct pxa3xx_nand_info *info = mtd->priv; | ||
| 1182 | |||
| 1183 | platform_set_drvdata(pdev, NULL); | ||
| 1184 | |||
| 1185 | del_mtd_device(mtd); | ||
| 1186 | del_mtd_partitions(mtd); | ||
| 1187 | free_irq(IRQ_NAND, info); | ||
| 1188 | if (use_dma) { | ||
| 1189 | pxa_free_dma(info->data_dma_ch); | ||
| 1190 | dma_free_writecombine(&pdev->dev, info->data_buff_size, | ||
| 1191 | info->data_buff, info->data_buff_phys); | ||
| 1192 | } else | ||
| 1193 | kfree(info->data_buff); | ||
| 1194 | kfree(mtd); | ||
| 1195 | return 0; | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | #ifdef CONFIG_PM | ||
| 1199 | static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) | ||
| 1200 | { | ||
| 1201 | struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); | ||
| 1202 | struct pxa3xx_nand_info *info = mtd->priv; | ||
| 1203 | |||
| 1204 | if (info->state != STATE_READY) { | ||
| 1205 | dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); | ||
| 1206 | return -EAGAIN; | ||
| 1207 | } | ||
| 1208 | |||
| 1209 | return 0; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | static int pxa3xx_nand_resume(struct platform_device *pdev) | ||
| 1213 | { | ||
| 1214 | struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); | ||
| 1215 | struct pxa3xx_nand_info *info = mtd->priv; | ||
| 1216 | |||
| 1217 | clk_enable(info->clk); | ||
| 1218 | |||
| 1219 | return pxa3xx_nand_config_flash(info); | ||
| 1220 | } | ||
| 1221 | #else | ||
| 1222 | #define pxa3xx_nand_suspend NULL | ||
| 1223 | #define pxa3xx_nand_resume NULL | ||
| 1224 | #endif | ||
| 1225 | |||
| 1226 | static struct platform_driver pxa3xx_nand_driver = { | ||
| 1227 | .driver = { | ||
| 1228 | .name = "pxa3xx-nand", | ||
| 1229 | }, | ||
| 1230 | .probe = pxa3xx_nand_probe, | ||
| 1231 | .remove = pxa3xx_nand_remove, | ||
| 1232 | .suspend = pxa3xx_nand_suspend, | ||
| 1233 | .resume = pxa3xx_nand_resume, | ||
| 1234 | }; | ||
| 1235 | |||
| 1236 | static int __init pxa3xx_nand_init(void) | ||
| 1237 | { | ||
| 1238 | return platform_driver_register(&pxa3xx_nand_driver); | ||
| 1239 | } | ||
| 1240 | module_init(pxa3xx_nand_init); | ||
| 1241 | |||
| 1242 | static void __exit pxa3xx_nand_exit(void) | ||
| 1243 | { | ||
| 1244 | platform_driver_unregister(&pxa3xx_nand_driver); | ||
| 1245 | } | ||
| 1246 | module_exit(pxa3xx_nand_exit); | ||
| 1247 | |||
| 1248 | MODULE_LICENSE("GPL"); | ||
| 1249 | MODULE_DESCRIPTION("PXA3xx NAND controller driver"); | ||
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c index 0f6ac250f434..26f88215bc47 100644 --- a/drivers/mtd/nand/rtc_from4.c +++ b/drivers/mtd/nand/rtc_from4.c | |||
| @@ -478,6 +478,7 @@ static int __init rtc_from4_init(void) | |||
| 478 | struct nand_chip *this; | 478 | struct nand_chip *this; |
| 479 | unsigned short bcr1, bcr2, wcr2; | 479 | unsigned short bcr1, bcr2, wcr2; |
| 480 | int i; | 480 | int i; |
| 481 | int ret; | ||
| 481 | 482 | ||
| 482 | /* Allocate memory for MTD device structure and private data */ | 483 | /* Allocate memory for MTD device structure and private data */ |
| 483 | rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); | 484 | rtc_from4_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL); |
| @@ -537,6 +538,22 @@ static int __init rtc_from4_init(void) | |||
| 537 | this->ecc.hwctl = rtc_from4_enable_hwecc; | 538 | this->ecc.hwctl = rtc_from4_enable_hwecc; |
| 538 | this->ecc.calculate = rtc_from4_calculate_ecc; | 539 | this->ecc.calculate = rtc_from4_calculate_ecc; |
| 539 | this->ecc.correct = rtc_from4_correct_data; | 540 | this->ecc.correct = rtc_from4_correct_data; |
| 541 | |||
| 542 | /* We could create the decoder on demand, if memory is a concern. | ||
| 543 | * This way we have it handy, if an error happens | ||
| 544 | * | ||
| 545 | * Symbolsize is 10 (bits) | ||
| 546 | * Primitve polynomial is x^10+x^3+1 | ||
| 547 | * first consecutive root is 0 | ||
| 548 | * primitve element to generate roots = 1 | ||
| 549 | * generator polinomial degree = 6 | ||
| 550 | */ | ||
| 551 | rs_decoder = init_rs(10, 0x409, 0, 1, 6); | ||
| 552 | if (!rs_decoder) { | ||
| 553 | printk(KERN_ERR "Could not create a RS decoder\n"); | ||
| 554 | ret = -ENOMEM; | ||
| 555 | goto err_1; | ||
| 556 | } | ||
| 540 | #else | 557 | #else |
| 541 | printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n"); | 558 | printk(KERN_INFO "rtc_from4_init: using software ECC detection.\n"); |
| 542 | 559 | ||
| @@ -549,8 +566,8 @@ static int __init rtc_from4_init(void) | |||
| 549 | 566 | ||
| 550 | /* Scan to find existence of the device */ | 567 | /* Scan to find existence of the device */ |
| 551 | if (nand_scan(rtc_from4_mtd, RTC_FROM4_MAX_CHIPS)) { | 568 | if (nand_scan(rtc_from4_mtd, RTC_FROM4_MAX_CHIPS)) { |
| 552 | kfree(rtc_from4_mtd); | 569 | ret = -ENXIO; |
| 553 | return -ENXIO; | 570 | goto err_2; |
| 554 | } | 571 | } |
| 555 | 572 | ||
| 556 | /* Perform 'device recovery' for each chip in case there was a power loss. */ | 573 | /* Perform 'device recovery' for each chip in case there was a power loss. */ |
| @@ -566,28 +583,19 @@ static int __init rtc_from4_init(void) | |||
| 566 | #endif | 583 | #endif |
| 567 | 584 | ||
| 568 | /* Register the partitions */ | 585 | /* Register the partitions */ |
| 569 | add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS); | 586 | ret = add_mtd_partitions(rtc_from4_mtd, partition_info, NUM_PARTITIONS); |
| 587 | if (ret) | ||
| 588 | goto err_3; | ||
| 570 | 589 | ||
| 571 | #ifdef RTC_FROM4_HWECC | ||
| 572 | /* We could create the decoder on demand, if memory is a concern. | ||
| 573 | * This way we have it handy, if an error happens | ||
| 574 | * | ||
| 575 | * Symbolsize is 10 (bits) | ||
| 576 | * Primitve polynomial is x^10+x^3+1 | ||
| 577 | * first consecutive root is 0 | ||
| 578 | * primitve element to generate roots = 1 | ||
| 579 | * generator polinomial degree = 6 | ||
| 580 | */ | ||
| 581 | rs_decoder = init_rs(10, 0x409, 0, 1, 6); | ||
| 582 | if (!rs_decoder) { | ||
| 583 | printk(KERN_ERR "Could not create a RS decoder\n"); | ||
| 584 | nand_release(rtc_from4_mtd); | ||
| 585 | kfree(rtc_from4_mtd); | ||
| 586 | return -ENOMEM; | ||
| 587 | } | ||
| 588 | #endif | ||
| 589 | /* Return happy */ | 590 | /* Return happy */ |
| 590 | return 0; | 591 | return 0; |
| 592 | err_3: | ||
| 593 | nand_release(rtc_from4_mtd); | ||
| 594 | err_2: | ||
| 595 | free_rs(rs_decoder); | ||
| 596 | err_1: | ||
| 597 | kfree(rtc_from4_mtd); | ||
| 598 | return ret; | ||
| 591 | } | 599 | } |
| 592 | 600 | ||
| 593 | module_init(rtc_from4_init); | 601 | module_init(rtc_from4_init); |
diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 9260ad947524..b34a460ab679 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c | |||
| @@ -119,8 +119,7 @@ struct s3c2410_nand_info { | |||
| 119 | void __iomem *sel_reg; | 119 | void __iomem *sel_reg; |
| 120 | int sel_bit; | 120 | int sel_bit; |
| 121 | int mtd_count; | 121 | int mtd_count; |
| 122 | 122 | unsigned long save_sel; | |
| 123 | unsigned long save_nfconf; | ||
| 124 | 123 | ||
| 125 | enum s3c_cpu_type cpu_type; | 124 | enum s3c_cpu_type cpu_type; |
| 126 | }; | 125 | }; |
| @@ -358,6 +357,14 @@ static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat, | |||
| 358 | if (diff0 == 0 && diff1 == 0 && diff2 == 0) | 357 | if (diff0 == 0 && diff1 == 0 && diff2 == 0) |
| 359 | return 0; /* ECC is ok */ | 358 | return 0; /* ECC is ok */ |
| 360 | 359 | ||
| 360 | /* sometimes people do not think about using the ECC, so check | ||
| 361 | * to see if we have an 0xff,0xff,0xff read ECC and then ignore | ||
| 362 | * the error, on the assumption that this is an un-eccd page. | ||
| 363 | */ | ||
| 364 | if (read_ecc[0] == 0xff && read_ecc[1] == 0xff && read_ecc[2] == 0xff | ||
| 365 | && info->platform->ignore_unset_ecc) | ||
| 366 | return 0; | ||
| 367 | |||
| 361 | /* Can we correct this ECC (ie, one row and column change). | 368 | /* Can we correct this ECC (ie, one row and column change). |
| 362 | * Note, this is similar to the 256 error code on smartmedia */ | 369 | * Note, this is similar to the 256 error code on smartmedia */ |
| 363 | 370 | ||
| @@ -473,7 +480,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u | |||
| 473 | ecc_code[1] = ecc >> 8; | 480 | ecc_code[1] = ecc >> 8; |
| 474 | ecc_code[2] = ecc >> 16; | 481 | ecc_code[2] = ecc >> 16; |
| 475 | 482 | ||
| 476 | pr_debug("%s: returning ecc %06lx\n", __func__, ecc); | 483 | pr_debug("%s: returning ecc %06lx\n", __func__, ecc & 0xffffff); |
| 477 | 484 | ||
| 478 | return 0; | 485 | return 0; |
| 479 | } | 486 | } |
| @@ -644,9 +651,6 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, | |||
| 644 | chip->ecc.calculate = s3c2410_nand_calculate_ecc; | 651 | chip->ecc.calculate = s3c2410_nand_calculate_ecc; |
| 645 | chip->ecc.correct = s3c2410_nand_correct_data; | 652 | chip->ecc.correct = s3c2410_nand_correct_data; |
| 646 | chip->ecc.mode = NAND_ECC_HW; | 653 | chip->ecc.mode = NAND_ECC_HW; |
| 647 | chip->ecc.size = 512; | ||
| 648 | chip->ecc.bytes = 3; | ||
| 649 | chip->ecc.layout = &nand_hw_eccoob; | ||
| 650 | 654 | ||
| 651 | switch (info->cpu_type) { | 655 | switch (info->cpu_type) { |
| 652 | case TYPE_S3C2410: | 656 | case TYPE_S3C2410: |
| @@ -668,6 +672,40 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, | |||
| 668 | } else { | 672 | } else { |
| 669 | chip->ecc.mode = NAND_ECC_SOFT; | 673 | chip->ecc.mode = NAND_ECC_SOFT; |
| 670 | } | 674 | } |
| 675 | |||
| 676 | if (set->ecc_layout != NULL) | ||
| 677 | chip->ecc.layout = set->ecc_layout; | ||
| 678 | |||
| 679 | if (set->disable_ecc) | ||
| 680 | chip->ecc.mode = NAND_ECC_NONE; | ||
| 681 | } | ||
| 682 | |||
| 683 | /* s3c2410_nand_update_chip | ||
| 684 | * | ||
| 685 | * post-probe chip update, to change any items, such as the | ||
| 686 | * layout for large page nand | ||
| 687 | */ | ||
| 688 | |||
| 689 | static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info, | ||
| 690 | struct s3c2410_nand_mtd *nmtd) | ||
| 691 | { | ||
| 692 | struct nand_chip *chip = &nmtd->chip; | ||
| 693 | |||
| 694 | printk("%s: chip %p: %d\n", __func__, chip, chip->page_shift); | ||
| 695 | |||
| 696 | if (hardware_ecc) { | ||
| 697 | /* change the behaviour depending on wether we are using | ||
| 698 | * the large or small page nand device */ | ||
| 699 | |||
| 700 | if (chip->page_shift > 10) { | ||
| 701 | chip->ecc.size = 256; | ||
| 702 | chip->ecc.bytes = 3; | ||
| 703 | } else { | ||
| 704 | chip->ecc.size = 512; | ||
| 705 | chip->ecc.bytes = 3; | ||
| 706 | chip->ecc.layout = &nand_hw_eccoob; | ||
| 707 | } | ||
| 708 | } | ||
| 671 | } | 709 | } |
| 672 | 710 | ||
| 673 | /* s3c2410_nand_probe | 711 | /* s3c2410_nand_probe |
| @@ -776,9 +814,12 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, | |||
| 776 | 814 | ||
| 777 | s3c2410_nand_init_chip(info, nmtd, sets); | 815 | s3c2410_nand_init_chip(info, nmtd, sets); |
| 778 | 816 | ||
| 779 | nmtd->scan_res = nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1); | 817 | nmtd->scan_res = nand_scan_ident(&nmtd->mtd, |
| 818 | (sets) ? sets->nr_chips : 1); | ||
| 780 | 819 | ||
| 781 | if (nmtd->scan_res == 0) { | 820 | if (nmtd->scan_res == 0) { |
| 821 | s3c2410_nand_update_chip(info, nmtd); | ||
| 822 | nand_scan_tail(&nmtd->mtd); | ||
| 782 | s3c2410_nand_add_partition(info, nmtd, sets); | 823 | s3c2410_nand_add_partition(info, nmtd, sets); |
| 783 | } | 824 | } |
| 784 | 825 | ||
| @@ -810,15 +851,14 @@ static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm) | |||
| 810 | struct s3c2410_nand_info *info = platform_get_drvdata(dev); | 851 | struct s3c2410_nand_info *info = platform_get_drvdata(dev); |
| 811 | 852 | ||
| 812 | if (info) { | 853 | if (info) { |
| 813 | info->save_nfconf = readl(info->regs + S3C2410_NFCONF); | 854 | info->save_sel = readl(info->sel_reg); |
| 814 | 855 | ||
| 815 | /* For the moment, we must ensure nFCE is high during | 856 | /* For the moment, we must ensure nFCE is high during |
| 816 | * the time we are suspended. This really should be | 857 | * the time we are suspended. This really should be |
| 817 | * handled by suspending the MTDs we are using, but | 858 | * handled by suspending the MTDs we are using, but |
| 818 | * that is currently not the case. */ | 859 | * that is currently not the case. */ |
| 819 | 860 | ||
| 820 | writel(info->save_nfconf | info->sel_bit, | 861 | writel(info->save_sel | info->sel_bit, info->sel_reg); |
| 821 | info->regs + S3C2410_NFCONF); | ||
| 822 | 862 | ||
| 823 | if (!allow_clk_stop(info)) | 863 | if (!allow_clk_stop(info)) |
| 824 | clk_disable(info->clk); | 864 | clk_disable(info->clk); |
| @@ -830,7 +870,7 @@ static int s3c24xx_nand_suspend(struct platform_device *dev, pm_message_t pm) | |||
| 830 | static int s3c24xx_nand_resume(struct platform_device *dev) | 870 | static int s3c24xx_nand_resume(struct platform_device *dev) |
| 831 | { | 871 | { |
| 832 | struct s3c2410_nand_info *info = platform_get_drvdata(dev); | 872 | struct s3c2410_nand_info *info = platform_get_drvdata(dev); |
| 833 | unsigned long nfconf; | 873 | unsigned long sel; |
| 834 | 874 | ||
| 835 | if (info) { | 875 | if (info) { |
| 836 | clk_enable(info->clk); | 876 | clk_enable(info->clk); |
| @@ -838,10 +878,10 @@ static int s3c24xx_nand_resume(struct platform_device *dev) | |||
| 838 | 878 | ||
| 839 | /* Restore the state of the nFCE line. */ | 879 | /* Restore the state of the nFCE line. */ |
| 840 | 880 | ||
| 841 | nfconf = readl(info->regs + S3C2410_NFCONF); | 881 | sel = readl(info->sel_reg); |
| 842 | nfconf &= ~info->sel_bit; | 882 | sel &= ~info->sel_bit; |
| 843 | nfconf |= info->save_nfconf & info->sel_bit; | 883 | sel |= info->save_sel & info->sel_bit; |
| 844 | writel(nfconf, info->regs + S3C2410_NFCONF); | 884 | writel(sel, info->sel_reg); |
| 845 | 885 | ||
| 846 | if (allow_clk_stop(info)) | 886 | if (allow_clk_stop(info)) |
| 847 | clk_disable(info->clk); | 887 | clk_disable(info->clk); |
| @@ -927,3 +967,6 @@ module_exit(s3c2410_nand_exit); | |||
| 927 | MODULE_LICENSE("GPL"); | 967 | MODULE_LICENSE("GPL"); |
| 928 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | 968 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); |
| 929 | MODULE_DESCRIPTION("S3C24XX MTD NAND driver"); | 969 | MODULE_DESCRIPTION("S3C24XX MTD NAND driver"); |
| 970 | MODULE_ALIAS("platform:s3c2410-nand"); | ||
| 971 | MODULE_ALIAS("platform:s3c2412-nand"); | ||
| 972 | MODULE_ALIAS("platform:s3c2440-nand"); | ||
diff --git a/drivers/mtd/nftlmount.c b/drivers/mtd/nftlmount.c index 0513cbc8834d..345e6eff89ce 100644 --- a/drivers/mtd/nftlmount.c +++ b/drivers/mtd/nftlmount.c | |||
| @@ -33,11 +33,6 @@ | |||
| 33 | 33 | ||
| 34 | char nftlmountrev[]="$Revision: 1.41 $"; | 34 | char nftlmountrev[]="$Revision: 1.41 $"; |
| 35 | 35 | ||
| 36 | extern int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, | ||
| 37 | size_t *retlen, uint8_t *buf); | ||
| 38 | extern int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, | ||
| 39 | size_t *retlen, uint8_t *buf); | ||
| 40 | |||
| 41 | /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the | 36 | /* find_boot_record: Find the NFTL Media Header and its Spare copy which contains the |
| 42 | * various device information of the NFTL partition and Bad Unit Table. Update | 37 | * various device information of the NFTL partition and Bad Unit Table. Update |
| 43 | * the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[] | 38 | * the ReplUnitTable[] table accroding to the Bad Unit Table. ReplUnitTable[] |
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c index f86e06934cd8..4f80c2fd89af 100644 --- a/drivers/mtd/ofpart.c +++ b/drivers/mtd/ofpart.c | |||
| @@ -72,3 +72,5 @@ int __devinit of_mtd_parse_partitions(struct device *dev, | |||
| 72 | return nr_parts; | 72 | return nr_parts; |
| 73 | } | 73 | } |
| 74 | EXPORT_SYMBOL(of_mtd_parse_partitions); | 74 | EXPORT_SYMBOL(of_mtd_parse_partitions); |
| 75 | |||
| 76 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 8d7d21be1541..5d7965f7e9ce 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c | |||
| @@ -329,6 +329,21 @@ static int onenand_wait(struct mtd_info *mtd, int state) | |||
| 329 | printk(KERN_ERR "onenand_wait: controller error = 0x%04x\n", ctrl); | 329 | printk(KERN_ERR "onenand_wait: controller error = 0x%04x\n", ctrl); |
| 330 | if (ctrl & ONENAND_CTRL_LOCK) | 330 | if (ctrl & ONENAND_CTRL_LOCK) |
| 331 | printk(KERN_ERR "onenand_wait: it's locked error.\n"); | 331 | printk(KERN_ERR "onenand_wait: it's locked error.\n"); |
| 332 | if (state == FL_READING) { | ||
| 333 | /* | ||
| 334 | * A power loss while writing can result in a page | ||
| 335 | * becoming unreadable. When the device is mounted | ||
| 336 | * again, reading that page gives controller errors. | ||
| 337 | * Upper level software like JFFS2 treat -EIO as fatal, | ||
| 338 | * refusing to mount at all. That means it is necessary | ||
| 339 | * to treat the error as an ECC error to allow recovery. | ||
| 340 | * Note that typically in this case, the eraseblock can | ||
| 341 | * still be erased and rewritten i.e. it has not become | ||
| 342 | * a bad block. | ||
| 343 | */ | ||
| 344 | mtd->ecc_stats.failed++; | ||
| 345 | return -EBADMSG; | ||
| 346 | } | ||
| 332 | return -EIO; | 347 | return -EIO; |
| 333 | } | 348 | } |
| 334 | 349 | ||
| @@ -1336,7 +1351,7 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len, | |||
| 1336 | } | 1351 | } |
| 1337 | 1352 | ||
| 1338 | /* Reject writes, which are not page aligned */ | 1353 | /* Reject writes, which are not page aligned */ |
| 1339 | if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) { | 1354 | if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) { |
| 1340 | printk(KERN_ERR "onenand_panic_write: Attempt to write not page aligned data\n"); | 1355 | printk(KERN_ERR "onenand_panic_write: Attempt to write not page aligned data\n"); |
| 1341 | return -EINVAL; | 1356 | return -EINVAL; |
| 1342 | } | 1357 | } |
| @@ -1466,7 +1481,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to, | |||
| 1466 | } | 1481 | } |
| 1467 | 1482 | ||
| 1468 | /* Reject writes, which are not page aligned */ | 1483 | /* Reject writes, which are not page aligned */ |
| 1469 | if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) { | 1484 | if (unlikely(NOTALIGNED(to) || NOTALIGNED(len))) { |
| 1470 | printk(KERN_ERR "onenand_write_ops_nolock: Attempt to write not page aligned data\n"); | 1485 | printk(KERN_ERR "onenand_write_ops_nolock: Attempt to write not page aligned data\n"); |
| 1471 | return -EINVAL; | 1486 | return -EINVAL; |
| 1472 | } | 1487 | } |
| @@ -2052,7 +2067,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) | |||
| 2052 | * | 2067 | * |
| 2053 | * Check lock status | 2068 | * Check lock status |
| 2054 | */ | 2069 | */ |
| 2055 | static void onenand_check_lock_status(struct onenand_chip *this) | 2070 | static int onenand_check_lock_status(struct onenand_chip *this) |
| 2056 | { | 2071 | { |
| 2057 | unsigned int value, block, status; | 2072 | unsigned int value, block, status; |
| 2058 | unsigned int end; | 2073 | unsigned int end; |
| @@ -2070,9 +2085,13 @@ static void onenand_check_lock_status(struct onenand_chip *this) | |||
| 2070 | 2085 | ||
| 2071 | /* Check lock status */ | 2086 | /* Check lock status */ |
| 2072 | status = this->read_word(this->base + ONENAND_REG_WP_STATUS); | 2087 | status = this->read_word(this->base + ONENAND_REG_WP_STATUS); |
| 2073 | if (!(status & ONENAND_WP_US)) | 2088 | if (!(status & ONENAND_WP_US)) { |
| 2074 | printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status); | 2089 | printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status); |
| 2090 | return 0; | ||
| 2091 | } | ||
| 2075 | } | 2092 | } |
| 2093 | |||
| 2094 | return 1; | ||
| 2076 | } | 2095 | } |
| 2077 | 2096 | ||
| 2078 | /** | 2097 | /** |
| @@ -2081,9 +2100,11 @@ static void onenand_check_lock_status(struct onenand_chip *this) | |||
| 2081 | * | 2100 | * |
| 2082 | * Unlock all blocks | 2101 | * Unlock all blocks |
| 2083 | */ | 2102 | */ |
| 2084 | static int onenand_unlock_all(struct mtd_info *mtd) | 2103 | static void onenand_unlock_all(struct mtd_info *mtd) |
| 2085 | { | 2104 | { |
| 2086 | struct onenand_chip *this = mtd->priv; | 2105 | struct onenand_chip *this = mtd->priv; |
| 2106 | loff_t ofs = 0; | ||
| 2107 | size_t len = this->chipsize; | ||
| 2087 | 2108 | ||
| 2088 | if (this->options & ONENAND_HAS_UNLOCK_ALL) { | 2109 | if (this->options & ONENAND_HAS_UNLOCK_ALL) { |
| 2089 | /* Set start block address */ | 2110 | /* Set start block address */ |
| @@ -2099,23 +2120,19 @@ static int onenand_unlock_all(struct mtd_info *mtd) | |||
| 2099 | & ONENAND_CTRL_ONGO) | 2120 | & ONENAND_CTRL_ONGO) |
| 2100 | continue; | 2121 | continue; |
| 2101 | 2122 | ||
| 2123 | /* Check lock status */ | ||
| 2124 | if (onenand_check_lock_status(this)) | ||
| 2125 | return; | ||
| 2126 | |||
| 2102 | /* Workaround for all block unlock in DDP */ | 2127 | /* Workaround for all block unlock in DDP */ |
| 2103 | if (ONENAND_IS_DDP(this)) { | 2128 | if (ONENAND_IS_DDP(this)) { |
| 2104 | /* 1st block on another chip */ | 2129 | /* All blocks on another chip */ |
| 2105 | loff_t ofs = this->chipsize >> 1; | 2130 | ofs = this->chipsize >> 1; |
| 2106 | size_t len = mtd->erasesize; | 2131 | len = this->chipsize >> 1; |
| 2107 | |||
| 2108 | onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK); | ||
| 2109 | } | 2132 | } |
| 2110 | |||
| 2111 | onenand_check_lock_status(this); | ||
| 2112 | |||
| 2113 | return 0; | ||
| 2114 | } | 2133 | } |
| 2115 | 2134 | ||
| 2116 | onenand_do_lock_cmd(mtd, 0x0, this->chipsize, ONENAND_CMD_UNLOCK); | 2135 | onenand_do_lock_cmd(mtd, ofs, len, ONENAND_CMD_UNLOCK); |
| 2117 | |||
| 2118 | return 0; | ||
| 2119 | } | 2136 | } |
| 2120 | 2137 | ||
| 2121 | #ifdef CONFIG_MTD_ONENAND_OTP | 2138 | #ifdef CONFIG_MTD_ONENAND_OTP |
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c index aecdd50a1781..2f53b51c6805 100644 --- a/drivers/mtd/onenand/onenand_bbt.c +++ b/drivers/mtd/onenand/onenand_bbt.c | |||
| @@ -17,9 +17,6 @@ | |||
| 17 | #include <linux/mtd/onenand.h> | 17 | #include <linux/mtd/onenand.h> |
| 18 | #include <linux/mtd/compatmac.h> | 18 | #include <linux/mtd/compatmac.h> |
| 19 | 19 | ||
| 20 | extern int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from, | ||
| 21 | struct mtd_oob_ops *ops); | ||
| 22 | |||
| 23 | /** | 20 | /** |
| 24 | * check_short_pattern - [GENERIC] check if a pattern is in the buffer | 21 | * check_short_pattern - [GENERIC] check if a pattern is in the buffer |
| 25 | * @param buf the buffer to search | 22 | * @param buf the buffer to search |
diff --git a/drivers/mtd/rfd_ftl.c b/drivers/mtd/rfd_ftl.c index 823fba4e6d2f..c84e45465499 100644 --- a/drivers/mtd/rfd_ftl.c +++ b/drivers/mtd/rfd_ftl.c | |||
| @@ -823,7 +823,7 @@ static void rfd_ftl_remove_dev(struct mtd_blktrans_dev *dev) | |||
| 823 | kfree(part); | 823 | kfree(part); |
| 824 | } | 824 | } |
| 825 | 825 | ||
| 826 | struct mtd_blktrans_ops rfd_ftl_tr = { | 826 | static struct mtd_blktrans_ops rfd_ftl_tr = { |
| 827 | .name = "rfd", | 827 | .name = "rfd", |
| 828 | .major = RFD_FTL_MAJOR, | 828 | .major = RFD_FTL_MAJOR, |
| 829 | .part_bits = PART_BITS, | 829 | .part_bits = PART_BITS, |
diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig index b9daf159a4a7..3f063108e95f 100644 --- a/drivers/mtd/ubi/Kconfig +++ b/drivers/mtd/ubi/Kconfig | |||
| @@ -24,8 +24,13 @@ config MTD_UBI_WL_THRESHOLD | |||
| 24 | erase counter value and the lowest erase counter value of eraseblocks | 24 | erase counter value and the lowest erase counter value of eraseblocks |
| 25 | of UBI devices. When this threshold is exceeded, UBI starts performing | 25 | of UBI devices. When this threshold is exceeded, UBI starts performing |
| 26 | wear leveling by means of moving data from eraseblock with low erase | 26 | wear leveling by means of moving data from eraseblock with low erase |
| 27 | counter to eraseblocks with high erase counter. Leave the default | 27 | counter to eraseblocks with high erase counter. |
| 28 | value if unsure. | 28 | |
| 29 | The default value should be OK for SLC NAND flashes, NOR flashes and | ||
| 30 | other flashes which have eraseblock life-cycle 100000 or more. | ||
| 31 | However, in case of MLC NAND flashes which typically have eraseblock | ||
| 32 | life-cycle less then 10000, the threshold should be lessened (e.g., | ||
| 33 | to 128 or 256, although it does not have to be power of 2). | ||
| 29 | 34 | ||
| 30 | config MTD_UBI_BEB_RESERVE | 35 | config MTD_UBI_BEB_RESERVE |
| 31 | int "Percentage of reserved eraseblocks for bad eraseblocks handling" | 36 | int "Percentage of reserved eraseblocks for bad eraseblocks handling" |
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 275960462970..961416ac0616 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c | |||
| @@ -606,8 +606,16 @@ static int io_init(struct ubi_device *ubi) | |||
| 606 | ubi->ro_mode = 1; | 606 | ubi->ro_mode = 1; |
| 607 | } | 607 | } |
| 608 | 608 | ||
| 609 | dbg_msg("leb_size %d", ubi->leb_size); | 609 | ubi_msg("physical eraseblock size: %d bytes (%d KiB)", |
| 610 | dbg_msg("ro_mode %d", ubi->ro_mode); | 610 | ubi->peb_size, ubi->peb_size >> 10); |
| 611 | ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size); | ||
| 612 | ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size); | ||
| 613 | if (ubi->hdrs_min_io_size != ubi->min_io_size) | ||
| 614 | ubi_msg("sub-page size: %d", | ||
| 615 | ubi->hdrs_min_io_size); | ||
| 616 | ubi_msg("VID header offset: %d (aligned %d)", | ||
| 617 | ubi->vid_hdr_offset, ubi->vid_hdr_aloffset); | ||
| 618 | ubi_msg("data offset: %d", ubi->leb_start); | ||
| 611 | 619 | ||
| 612 | /* | 620 | /* |
| 613 | * Note, ideally, we have to initialize ubi->bad_peb_count here. But | 621 | * Note, ideally, we have to initialize ubi->bad_peb_count here. But |
| @@ -755,8 +763,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
| 755 | mutex_init(&ubi->volumes_mutex); | 763 | mutex_init(&ubi->volumes_mutex); |
| 756 | spin_lock_init(&ubi->volumes_lock); | 764 | spin_lock_init(&ubi->volumes_lock); |
| 757 | 765 | ||
| 758 | dbg_msg("attaching mtd%d to ubi%d: VID header offset %d", | 766 | ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num); |
| 759 | mtd->index, ubi_num, vid_hdr_offset); | ||
| 760 | 767 | ||
| 761 | err = io_init(ubi); | 768 | err = io_init(ubi); |
| 762 | if (err) | 769 | if (err) |
| @@ -804,15 +811,8 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int vid_hdr_offset) | |||
| 804 | ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num); | 811 | ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num); |
| 805 | ubi_msg("MTD device name: \"%s\"", mtd->name); | 812 | ubi_msg("MTD device name: \"%s\"", mtd->name); |
| 806 | ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20); | 813 | ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> 20); |
| 807 | ubi_msg("physical eraseblock size: %d bytes (%d KiB)", | ||
| 808 | ubi->peb_size, ubi->peb_size >> 10); | ||
| 809 | ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size); | ||
| 810 | ubi_msg("number of good PEBs: %d", ubi->good_peb_count); | 814 | ubi_msg("number of good PEBs: %d", ubi->good_peb_count); |
| 811 | ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count); | 815 | ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count); |
| 812 | ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size); | ||
| 813 | ubi_msg("VID header offset: %d (aligned %d)", | ||
| 814 | ubi->vid_hdr_offset, ubi->vid_hdr_aloffset); | ||
| 815 | ubi_msg("data offset: %d", ubi->leb_start); | ||
| 816 | ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots); | 816 | ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots); |
| 817 | ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD); | 817 | ubi_msg("wear-leveling threshold: %d", CONFIG_MTD_UBI_WL_THRESHOLD); |
| 818 | ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT); | 818 | ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT); |
| @@ -950,8 +950,7 @@ static int __init ubi_init(void) | |||
| 950 | BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64); | 950 | BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64); |
| 951 | 951 | ||
| 952 | if (mtd_devs > UBI_MAX_DEVICES) { | 952 | if (mtd_devs > UBI_MAX_DEVICES) { |
| 953 | printk(KERN_ERR "UBI error: too many MTD devices, " | 953 | ubi_err("too many MTD devices, maximum is %d", UBI_MAX_DEVICES); |
| 954 | "maximum is %d\n", UBI_MAX_DEVICES); | ||
| 955 | return -EINVAL; | 954 | return -EINVAL; |
| 956 | } | 955 | } |
| 957 | 956 | ||
| @@ -959,25 +958,25 @@ static int __init ubi_init(void) | |||
| 959 | ubi_class = class_create(THIS_MODULE, UBI_NAME_STR); | 958 | ubi_class = class_create(THIS_MODULE, UBI_NAME_STR); |
| 960 | if (IS_ERR(ubi_class)) { | 959 | if (IS_ERR(ubi_class)) { |
| 961 | err = PTR_ERR(ubi_class); | 960 | err = PTR_ERR(ubi_class); |
| 962 | printk(KERN_ERR "UBI error: cannot create UBI class\n"); | 961 | ubi_err("cannot create UBI class"); |
| 963 | goto out; | 962 | goto out; |
| 964 | } | 963 | } |
| 965 | 964 | ||
| 966 | err = class_create_file(ubi_class, &ubi_version); | 965 | err = class_create_file(ubi_class, &ubi_version); |
| 967 | if (err) { | 966 | if (err) { |
| 968 | printk(KERN_ERR "UBI error: cannot create sysfs file\n"); | 967 | ubi_err("cannot create sysfs file"); |
| 969 | goto out_class; | 968 | goto out_class; |
| 970 | } | 969 | } |
| 971 | 970 | ||
| 972 | err = misc_register(&ubi_ctrl_cdev); | 971 | err = misc_register(&ubi_ctrl_cdev); |
| 973 | if (err) { | 972 | if (err) { |
| 974 | printk(KERN_ERR "UBI error: cannot register device\n"); | 973 | ubi_err("cannot register device"); |
| 975 | goto out_version; | 974 | goto out_version; |
| 976 | } | 975 | } |
| 977 | 976 | ||
| 978 | ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", | 977 | ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", |
| 979 | sizeof(struct ubi_wl_entry), | 978 | sizeof(struct ubi_wl_entry), |
| 980 | 0, 0, NULL); | 979 | 0, 0, NULL); |
| 981 | if (!ubi_wl_entry_slab) | 980 | if (!ubi_wl_entry_slab) |
| 982 | goto out_dev_unreg; | 981 | goto out_dev_unreg; |
| 983 | 982 | ||
| @@ -1000,8 +999,7 @@ static int __init ubi_init(void) | |||
| 1000 | mutex_unlock(&ubi_devices_mutex); | 999 | mutex_unlock(&ubi_devices_mutex); |
| 1001 | if (err < 0) { | 1000 | if (err < 0) { |
| 1002 | put_mtd_device(mtd); | 1001 | put_mtd_device(mtd); |
| 1003 | printk(KERN_ERR "UBI error: cannot attach mtd%d\n", | 1002 | ubi_err("cannot attach mtd%d", mtd->index); |
| 1004 | mtd->index); | ||
| 1005 | goto out_detach; | 1003 | goto out_detach; |
| 1006 | } | 1004 | } |
| 1007 | } | 1005 | } |
| @@ -1023,7 +1021,7 @@ out_version: | |||
| 1023 | out_class: | 1021 | out_class: |
| 1024 | class_destroy(ubi_class); | 1022 | class_destroy(ubi_class); |
| 1025 | out: | 1023 | out: |
| 1026 | printk(KERN_ERR "UBI error: cannot initialize UBI, error %d\n", err); | 1024 | ubi_err("UBI error: cannot initialize UBI, error %d", err); |
| 1027 | return err; | 1025 | return err; |
| 1028 | } | 1026 | } |
| 1029 | module_init(ubi_init); | 1027 | module_init(ubi_init); |
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index 51c40b17f1ec..8ea99d8c9e1f 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h | |||
| @@ -41,7 +41,7 @@ | |||
| 41 | /* Generic debugging message */ | 41 | /* Generic debugging message */ |
| 42 | #define dbg_msg(fmt, ...) \ | 42 | #define dbg_msg(fmt, ...) \ |
| 43 | printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \ | 43 | printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \ |
| 44 | current->pid, __FUNCTION__, ##__VA_ARGS__) | 44 | current->pid, __func__, ##__VA_ARGS__) |
| 45 | 45 | ||
| 46 | #define ubi_dbg_dump_stack() dump_stack() | 46 | #define ubi_dbg_dump_stack() dump_stack() |
| 47 | 47 | ||
| @@ -99,8 +99,10 @@ void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req); | |||
| 99 | #ifdef CONFIG_MTD_UBI_DEBUG_MSG_BLD | 99 | #ifdef CONFIG_MTD_UBI_DEBUG_MSG_BLD |
| 100 | /* Initialization and build messages */ | 100 | /* Initialization and build messages */ |
| 101 | #define dbg_bld(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) | 101 | #define dbg_bld(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__) |
| 102 | #define UBI_IO_DEBUG 1 | ||
| 102 | #else | 103 | #else |
| 103 | #define dbg_bld(fmt, ...) ({}) | 104 | #define dbg_bld(fmt, ...) ({}) |
| 105 | #define UBI_IO_DEBUG 0 | ||
| 104 | #endif | 106 | #endif |
| 105 | 107 | ||
| 106 | #ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS | 108 | #ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS |
diff --git a/drivers/mtd/ubi/gluebi.c b/drivers/mtd/ubi/gluebi.c index d397219238d3..e909b390069a 100644 --- a/drivers/mtd/ubi/gluebi.c +++ b/drivers/mtd/ubi/gluebi.c | |||
| @@ -291,11 +291,12 @@ int ubi_create_gluebi(struct ubi_device *ubi, struct ubi_volume *vol) | |||
| 291 | /* | 291 | /* |
| 292 | * In case of dynamic volume, MTD device size is just volume size. In | 292 | * In case of dynamic volume, MTD device size is just volume size. In |
| 293 | * case of a static volume the size is equivalent to the amount of data | 293 | * case of a static volume the size is equivalent to the amount of data |
| 294 | * bytes, which is zero at this moment and will be changed after volume | 294 | * bytes. |
| 295 | * update. | ||
| 296 | */ | 295 | */ |
| 297 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) | 296 | if (vol->vol_type == UBI_DYNAMIC_VOLUME) |
| 298 | mtd->size = vol->usable_leb_size * vol->reserved_pebs; | 297 | mtd->size = vol->usable_leb_size * vol->reserved_pebs; |
| 298 | else | ||
| 299 | mtd->size = vol->used_bytes; | ||
| 299 | 300 | ||
| 300 | if (add_mtd_device(mtd)) { | 301 | if (add_mtd_device(mtd)) { |
| 301 | ubi_err("cannot not add MTD device\n"); | 302 | ubi_err("cannot not add MTD device\n"); |
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index db3efdef2433..4ac11df7b048 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
| @@ -631,6 +631,8 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, | |||
| 631 | 631 | ||
| 632 | dbg_io("read EC header from PEB %d", pnum); | 632 | dbg_io("read EC header from PEB %d", pnum); |
| 633 | ubi_assert(pnum >= 0 && pnum < ubi->peb_count); | 633 | ubi_assert(pnum >= 0 && pnum < ubi->peb_count); |
| 634 | if (UBI_IO_DEBUG) | ||
| 635 | verbose = 1; | ||
| 634 | 636 | ||
| 635 | err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE); | 637 | err = ubi_io_read(ubi, ec_hdr, pnum, 0, UBI_EC_HDR_SIZE); |
| 636 | if (err) { | 638 | if (err) { |
| @@ -904,6 +906,8 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, | |||
| 904 | 906 | ||
| 905 | dbg_io("read VID header from PEB %d", pnum); | 907 | dbg_io("read VID header from PEB %d", pnum); |
| 906 | ubi_assert(pnum >= 0 && pnum < ubi->peb_count); | 908 | ubi_assert(pnum >= 0 && pnum < ubi->peb_count); |
| 909 | if (UBI_IO_DEBUG) | ||
| 910 | verbose = 1; | ||
| 907 | 911 | ||
| 908 | p = (char *)vid_hdr - ubi->vid_hdr_shift; | 912 | p = (char *)vid_hdr - ubi->vid_hdr_shift; |
| 909 | err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, | 913 | err = ubi_io_read(ubi, p, pnum, ubi->vid_hdr_aloffset, |
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 05aa3e7daba1..96d410e106ab 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | 42 | ||
| 43 | #include <linux/err.h> | 43 | #include <linux/err.h> |
| 44 | #include <linux/crc32.h> | 44 | #include <linux/crc32.h> |
| 45 | #include <asm/div64.h> | ||
| 45 | #include "ubi.h" | 46 | #include "ubi.h" |
| 46 | 47 | ||
| 47 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | 48 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID |
| @@ -92,27 +93,6 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, | |||
| 92 | } | 93 | } |
| 93 | 94 | ||
| 94 | /** | 95 | /** |
| 95 | * commit_to_mean_value - commit intermediate results to the final mean erase | ||
| 96 | * counter value. | ||
| 97 | * @si: scanning information | ||
| 98 | * | ||
| 99 | * This is a helper function which calculates partial mean erase counter mean | ||
| 100 | * value and adds it to the resulting mean value. As we can work only in | ||
| 101 | * integer arithmetic and we want to calculate the mean value of erase counter | ||
| 102 | * accurately, we first sum erase counter values in @si->ec_sum variable and | ||
| 103 | * count these components in @si->ec_count. If this temporary @si->ec_sum is | ||
| 104 | * going to overflow, we calculate the partial mean value | ||
| 105 | * (@si->ec_sum/@si->ec_count) and add it to @si->mean_ec. | ||
| 106 | */ | ||
| 107 | static void commit_to_mean_value(struct ubi_scan_info *si) | ||
| 108 | { | ||
| 109 | si->ec_sum /= si->ec_count; | ||
| 110 | if (si->ec_sum % si->ec_count >= si->ec_count / 2) | ||
| 111 | si->mean_ec += 1; | ||
| 112 | si->mean_ec += si->ec_sum; | ||
| 113 | } | ||
| 114 | |||
| 115 | /** | ||
| 116 | * validate_vid_hdr - check that volume identifier header is correct and | 96 | * validate_vid_hdr - check that volume identifier header is correct and |
| 117 | * consistent. | 97 | * consistent. |
| 118 | * @vid_hdr: the volume identifier header to check | 98 | * @vid_hdr: the volume identifier header to check |
| @@ -901,15 +881,8 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, int pnum | |||
| 901 | 881 | ||
| 902 | adjust_mean_ec: | 882 | adjust_mean_ec: |
| 903 | if (!ec_corr) { | 883 | if (!ec_corr) { |
| 904 | if (si->ec_sum + ec < ec) { | 884 | si->ec_sum += ec; |
| 905 | commit_to_mean_value(si); | 885 | si->ec_count += 1; |
| 906 | si->ec_sum = 0; | ||
| 907 | si->ec_count = 0; | ||
| 908 | } else { | ||
| 909 | si->ec_sum += ec; | ||
| 910 | si->ec_count += 1; | ||
| 911 | } | ||
| 912 | |||
| 913 | if (ec > si->max_ec) | 886 | if (ec > si->max_ec) |
| 914 | si->max_ec = ec; | 887 | si->max_ec = ec; |
| 915 | if (ec < si->min_ec) | 888 | if (ec < si->min_ec) |
| @@ -965,9 +938,11 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) | |||
| 965 | 938 | ||
| 966 | dbg_msg("scanning is finished"); | 939 | dbg_msg("scanning is finished"); |
| 967 | 940 | ||
| 968 | /* Finish mean erase counter calculations */ | 941 | /* Calculate mean erase counter */ |
| 969 | if (si->ec_count) | 942 | if (si->ec_count) { |
| 970 | commit_to_mean_value(si); | 943 | do_div(si->ec_sum, si->ec_count); |
| 944 | si->mean_ec = si->ec_sum; | ||
| 945 | } | ||
| 971 | 946 | ||
| 972 | if (si->is_empty) | 947 | if (si->is_empty) |
| 973 | ubi_msg("empty MTD device detected"); | 948 | ubi_msg("empty MTD device detected"); |
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h index 46d444af471a..966b9b682a42 100644 --- a/drivers/mtd/ubi/scan.h +++ b/drivers/mtd/ubi/scan.h | |||
| @@ -124,7 +124,7 @@ struct ubi_scan_info { | |||
| 124 | int max_ec; | 124 | int max_ec; |
| 125 | unsigned long long max_sqnum; | 125 | unsigned long long max_sqnum; |
| 126 | int mean_ec; | 126 | int mean_ec; |
| 127 | int ec_sum; | 127 | uint64_t ec_sum; |
| 128 | int ec_count; | 128 | int ec_count; |
| 129 | }; | 129 | }; |
| 130 | 130 | ||
diff --git a/include/mtd/ubi-header.h b/drivers/mtd/ubi/ubi-media.h index 292f916ea564..c3185d9fd048 100644 --- a/include/mtd/ubi-header.h +++ b/drivers/mtd/ubi/ubi-media.h | |||
| @@ -24,11 +24,11 @@ | |||
| 24 | 24 | ||
| 25 | /* | 25 | /* |
| 26 | * This file defines the layout of UBI headers and all the other UBI on-flash | 26 | * This file defines the layout of UBI headers and all the other UBI on-flash |
| 27 | * data structures. May be included by user-space. | 27 | * data structures. |
| 28 | */ | 28 | */ |
| 29 | 29 | ||
| 30 | #ifndef __UBI_HEADER_H__ | 30 | #ifndef __UBI_MEDIA_H__ |
| 31 | #define __UBI_HEADER_H__ | 31 | #define __UBI_MEDIA_H__ |
| 32 | 32 | ||
| 33 | #include <asm/byteorder.h> | 33 | #include <asm/byteorder.h> |
| 34 | 34 | ||
| @@ -369,4 +369,4 @@ struct ubi_vtbl_record { | |||
| 369 | __be32 crc; | 369 | __be32 crc; |
| 370 | } __attribute__ ((packed)); | 370 | } __attribute__ ((packed)); |
| 371 | 371 | ||
| 372 | #endif /* !__UBI_HEADER_H__ */ | 372 | #endif /* !__UBI_MEDIA_H__ */ |
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index a548c1d28fa8..67dcbd11c15c 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h | |||
| @@ -37,10 +37,9 @@ | |||
| 37 | #include <linux/string.h> | 37 | #include <linux/string.h> |
| 38 | #include <linux/vmalloc.h> | 38 | #include <linux/vmalloc.h> |
| 39 | #include <linux/mtd/mtd.h> | 39 | #include <linux/mtd/mtd.h> |
| 40 | |||
| 41 | #include <mtd/ubi-header.h> | ||
| 42 | #include <linux/mtd/ubi.h> | 40 | #include <linux/mtd/ubi.h> |
| 43 | 41 | ||
| 42 | #include "ubi-media.h" | ||
| 44 | #include "scan.h" | 43 | #include "scan.h" |
| 45 | #include "debug.h" | 44 | #include "debug.h" |
| 46 | 45 | ||
| @@ -54,10 +53,10 @@ | |||
| 54 | #define ubi_msg(fmt, ...) printk(KERN_NOTICE "UBI: " fmt "\n", ##__VA_ARGS__) | 53 | #define ubi_msg(fmt, ...) printk(KERN_NOTICE "UBI: " fmt "\n", ##__VA_ARGS__) |
| 55 | /* UBI warning messages */ | 54 | /* UBI warning messages */ |
| 56 | #define ubi_warn(fmt, ...) printk(KERN_WARNING "UBI warning: %s: " fmt "\n", \ | 55 | #define ubi_warn(fmt, ...) printk(KERN_WARNING "UBI warning: %s: " fmt "\n", \ |
| 57 | __FUNCTION__, ##__VA_ARGS__) | 56 | __func__, ##__VA_ARGS__) |
| 58 | /* UBI error messages */ | 57 | /* UBI error messages */ |
| 59 | #define ubi_err(fmt, ...) printk(KERN_ERR "UBI error: %s: " fmt "\n", \ | 58 | #define ubi_err(fmt, ...) printk(KERN_ERR "UBI error: %s: " fmt "\n", \ |
| 60 | __FUNCTION__, ##__VA_ARGS__) | 59 | __func__, ##__VA_ARGS__) |
| 61 | 60 | ||
| 62 | /* Lowest number PEBs reserved for bad PEB handling */ | 61 | /* Lowest number PEBs reserved for bad PEB handling */ |
| 63 | #define MIN_RESEVED_PEBS 2 | 62 | #define MIN_RESEVED_PEBS 2 |
diff --git a/drivers/net/arm/at91_ether.c b/drivers/net/arm/at91_ether.c index 978e20a1791b..1e39e78f1778 100644 --- a/drivers/net/arm/at91_ether.c +++ b/drivers/net/arm/at91_ether.c | |||
| @@ -1248,3 +1248,4 @@ module_exit(at91ether_exit) | |||
| 1248 | MODULE_LICENSE("GPL"); | 1248 | MODULE_LICENSE("GPL"); |
| 1249 | MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver"); | 1249 | MODULE_DESCRIPTION("AT91RM9200 EMAC Ethernet driver"); |
| 1250 | MODULE_AUTHOR("Andrew Victor"); | 1250 | MODULE_AUTHOR("Andrew Victor"); |
| 1251 | MODULE_ALIAS("platform:" DRV_NAME); | ||
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 91a6590d107b..ecd8fc6146e9 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c | |||
| @@ -897,6 +897,7 @@ static struct platform_driver ep93xx_eth_driver = { | |||
| 897 | .remove = ep93xx_eth_remove, | 897 | .remove = ep93xx_eth_remove, |
| 898 | .driver = { | 898 | .driver = { |
| 899 | .name = "ep93xx-eth", | 899 | .name = "ep93xx-eth", |
| 900 | .owner = THIS_MODULE, | ||
| 900 | }, | 901 | }, |
| 901 | }; | 902 | }; |
| 902 | 903 | ||
| @@ -914,3 +915,4 @@ static void __exit ep93xx_eth_cleanup_module(void) | |||
| 914 | module_init(ep93xx_eth_init_module); | 915 | module_init(ep93xx_eth_init_module); |
| 915 | module_exit(ep93xx_eth_cleanup_module); | 916 | module_exit(ep93xx_eth_cleanup_module); |
| 916 | MODULE_LICENSE("GPL"); | 917 | MODULE_LICENSE("GPL"); |
| 918 | MODULE_ALIAS("platform:ep93xx-eth"); | ||
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 5586fc624688..0afe522b8f7b 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c | |||
| @@ -91,6 +91,144 @@ | |||
| 91 | #include "atlx.c" | 91 | #include "atlx.c" |
| 92 | 92 | ||
| 93 | /* | 93 | /* |
| 94 | * This is the only thing that needs to be changed to adjust the | ||
| 95 | * maximum number of ports that the driver can manage. | ||
| 96 | */ | ||
| 97 | #define ATL1_MAX_NIC 4 | ||
| 98 | |||
| 99 | #define OPTION_UNSET -1 | ||
| 100 | #define OPTION_DISABLED 0 | ||
| 101 | #define OPTION_ENABLED 1 | ||
| 102 | |||
| 103 | #define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET } | ||
| 104 | |||
| 105 | /* | ||
| 106 | * Interrupt Moderate Timer in units of 2 us | ||
| 107 | * | ||
| 108 | * Valid Range: 10-65535 | ||
| 109 | * | ||
| 110 | * Default Value: 100 (200us) | ||
| 111 | */ | ||
| 112 | static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT; | ||
| 113 | static int num_int_mod_timer; | ||
| 114 | module_param_array_named(int_mod_timer, int_mod_timer, int, | ||
| 115 | &num_int_mod_timer, 0); | ||
| 116 | MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer"); | ||
| 117 | |||
| 118 | #define DEFAULT_INT_MOD_CNT 100 /* 200us */ | ||
| 119 | #define MAX_INT_MOD_CNT 65000 | ||
| 120 | #define MIN_INT_MOD_CNT 50 | ||
| 121 | |||
| 122 | struct atl1_option { | ||
| 123 | enum { enable_option, range_option, list_option } type; | ||
| 124 | char *name; | ||
| 125 | char *err; | ||
| 126 | int def; | ||
| 127 | union { | ||
| 128 | struct { /* range_option info */ | ||
| 129 | int min; | ||
| 130 | int max; | ||
| 131 | } r; | ||
| 132 | struct { /* list_option info */ | ||
| 133 | int nr; | ||
| 134 | struct atl1_opt_list { | ||
| 135 | int i; | ||
| 136 | char *str; | ||
| 137 | } *p; | ||
| 138 | } l; | ||
| 139 | } arg; | ||
| 140 | }; | ||
| 141 | |||
| 142 | static int __devinit atl1_validate_option(int *value, struct atl1_option *opt, | ||
| 143 | struct pci_dev *pdev) | ||
| 144 | { | ||
| 145 | if (*value == OPTION_UNSET) { | ||
| 146 | *value = opt->def; | ||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | |||
| 150 | switch (opt->type) { | ||
| 151 | case enable_option: | ||
| 152 | switch (*value) { | ||
| 153 | case OPTION_ENABLED: | ||
| 154 | dev_info(&pdev->dev, "%s enabled\n", opt->name); | ||
| 155 | return 0; | ||
| 156 | case OPTION_DISABLED: | ||
| 157 | dev_info(&pdev->dev, "%s disabled\n", opt->name); | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | break; | ||
| 161 | case range_option: | ||
| 162 | if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { | ||
| 163 | dev_info(&pdev->dev, "%s set to %i\n", opt->name, | ||
| 164 | *value); | ||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | break; | ||
| 168 | case list_option:{ | ||
| 169 | int i; | ||
| 170 | struct atl1_opt_list *ent; | ||
| 171 | |||
| 172 | for (i = 0; i < opt->arg.l.nr; i++) { | ||
| 173 | ent = &opt->arg.l.p[i]; | ||
| 174 | if (*value == ent->i) { | ||
| 175 | if (ent->str[0] != '\0') | ||
| 176 | dev_info(&pdev->dev, "%s\n", | ||
| 177 | ent->str); | ||
| 178 | return 0; | ||
| 179 | } | ||
| 180 | } | ||
| 181 | } | ||
| 182 | break; | ||
| 183 | |||
| 184 | default: | ||
| 185 | break; | ||
| 186 | } | ||
| 187 | |||
| 188 | dev_info(&pdev->dev, "invalid %s specified (%i) %s\n", | ||
| 189 | opt->name, *value, opt->err); | ||
| 190 | *value = opt->def; | ||
| 191 | return -1; | ||
| 192 | } | ||
| 193 | |||
| 194 | /* | ||
| 195 | * atl1_check_options - Range Checking for Command Line Parameters | ||
| 196 | * @adapter: board private structure | ||
| 197 | * | ||
| 198 | * This routine checks all command line parameters for valid user | ||
| 199 | * input. If an invalid value is given, or if no user specified | ||
| 200 | * value exists, a default value is used. The final value is stored | ||
| 201 | * in a variable in the adapter structure. | ||
| 202 | */ | ||
| 203 | void __devinit atl1_check_options(struct atl1_adapter *adapter) | ||
| 204 | { | ||
| 205 | struct pci_dev *pdev = adapter->pdev; | ||
| 206 | int bd = adapter->bd_number; | ||
| 207 | if (bd >= ATL1_MAX_NIC) { | ||
| 208 | dev_notice(&pdev->dev, "no configuration for board#%i\n", bd); | ||
| 209 | dev_notice(&pdev->dev, "using defaults for all values\n"); | ||
| 210 | } | ||
| 211 | { /* Interrupt Moderate Timer */ | ||
| 212 | struct atl1_option opt = { | ||
| 213 | .type = range_option, | ||
| 214 | .name = "Interrupt Moderator Timer", | ||
| 215 | .err = "using default of " | ||
| 216 | __MODULE_STRING(DEFAULT_INT_MOD_CNT), | ||
| 217 | .def = DEFAULT_INT_MOD_CNT, | ||
| 218 | .arg = {.r = {.min = MIN_INT_MOD_CNT, | ||
| 219 | .max = MAX_INT_MOD_CNT} } | ||
| 220 | }; | ||
| 221 | int val; | ||
| 222 | if (num_int_mod_timer > bd) { | ||
| 223 | val = int_mod_timer[bd]; | ||
| 224 | atl1_validate_option(&val, &opt, pdev); | ||
| 225 | adapter->imt = (u16) val; | ||
| 226 | } else | ||
| 227 | adapter->imt = (u16) (opt.def); | ||
| 228 | } | ||
| 229 | } | ||
| 230 | |||
| 231 | /* | ||
| 94 | * atl1_pci_tbl - PCI Device ID Table | 232 | * atl1_pci_tbl - PCI Device ID Table |
| 95 | */ | 233 | */ |
| 96 | static const struct pci_device_id atl1_pci_tbl[] = { | 234 | static const struct pci_device_id atl1_pci_tbl[] = { |
diff --git a/drivers/net/atlx/atlx.c b/drivers/net/atlx/atlx.c index 4186326d1b94..f06b854e2501 100644 --- a/drivers/net/atlx/atlx.c +++ b/drivers/net/atlx/atlx.c | |||
| @@ -253,181 +253,4 @@ static void atlx_restore_vlan(struct atlx_adapter *adapter) | |||
| 253 | atlx_vlan_rx_register(adapter->netdev, adapter->vlgrp); | 253 | atlx_vlan_rx_register(adapter->netdev, adapter->vlgrp); |
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | /* | ||
| 257 | * This is the only thing that needs to be changed to adjust the | ||
| 258 | * maximum number of ports that the driver can manage. | ||
| 259 | */ | ||
| 260 | #define ATL1_MAX_NIC 4 | ||
| 261 | |||
| 262 | #define OPTION_UNSET -1 | ||
| 263 | #define OPTION_DISABLED 0 | ||
| 264 | #define OPTION_ENABLED 1 | ||
| 265 | |||
| 266 | #define ATL1_PARAM_INIT { [0 ... ATL1_MAX_NIC] = OPTION_UNSET } | ||
| 267 | |||
| 268 | /* | ||
| 269 | * Interrupt Moderate Timer in units of 2 us | ||
| 270 | * | ||
| 271 | * Valid Range: 10-65535 | ||
| 272 | * | ||
| 273 | * Default Value: 100 (200us) | ||
| 274 | */ | ||
| 275 | static int __devinitdata int_mod_timer[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT; | ||
| 276 | static int num_int_mod_timer; | ||
| 277 | module_param_array_named(int_mod_timer, int_mod_timer, int, | ||
| 278 | &num_int_mod_timer, 0); | ||
| 279 | MODULE_PARM_DESC(int_mod_timer, "Interrupt moderator timer"); | ||
| 280 | |||
| 281 | /* | ||
| 282 | * flash_vendor | ||
| 283 | * | ||
| 284 | * Valid Range: 0-2 | ||
| 285 | * | ||
| 286 | * 0 - Atmel | ||
| 287 | * 1 - SST | ||
| 288 | * 2 - ST | ||
| 289 | * | ||
| 290 | * Default Value: 0 | ||
| 291 | */ | ||
| 292 | static int __devinitdata flash_vendor[ATL1_MAX_NIC+1] = ATL1_PARAM_INIT; | ||
| 293 | static int num_flash_vendor; | ||
| 294 | module_param_array_named(flash_vendor, flash_vendor, int, &num_flash_vendor, 0); | ||
| 295 | MODULE_PARM_DESC(flash_vendor, "SPI flash vendor"); | ||
| 296 | |||
| 297 | #define DEFAULT_INT_MOD_CNT 100 /* 200us */ | ||
| 298 | #define MAX_INT_MOD_CNT 65000 | ||
| 299 | #define MIN_INT_MOD_CNT 50 | ||
| 300 | |||
| 301 | #define FLASH_VENDOR_DEFAULT 0 | ||
| 302 | #define FLASH_VENDOR_MIN 0 | ||
| 303 | #define FLASH_VENDOR_MAX 2 | ||
| 304 | |||
| 305 | struct atl1_option { | ||
| 306 | enum { enable_option, range_option, list_option } type; | ||
| 307 | char *name; | ||
| 308 | char *err; | ||
| 309 | int def; | ||
| 310 | union { | ||
| 311 | struct { /* range_option info */ | ||
| 312 | int min; | ||
| 313 | int max; | ||
| 314 | } r; | ||
| 315 | struct { /* list_option info */ | ||
| 316 | int nr; | ||
| 317 | struct atl1_opt_list { | ||
| 318 | int i; | ||
| 319 | char *str; | ||
| 320 | } *p; | ||
| 321 | } l; | ||
| 322 | } arg; | ||
| 323 | }; | ||
| 324 | |||
| 325 | static int __devinit atl1_validate_option(int *value, struct atl1_option *opt, | ||
| 326 | struct pci_dev *pdev) | ||
| 327 | { | ||
| 328 | if (*value == OPTION_UNSET) { | ||
| 329 | *value = opt->def; | ||
| 330 | return 0; | ||
| 331 | } | ||
| 332 | |||
| 333 | switch (opt->type) { | ||
| 334 | case enable_option: | ||
| 335 | switch (*value) { | ||
| 336 | case OPTION_ENABLED: | ||
| 337 | dev_info(&pdev->dev, "%s enabled\n", opt->name); | ||
| 338 | return 0; | ||
| 339 | case OPTION_DISABLED: | ||
| 340 | dev_info(&pdev->dev, "%s disabled\n", opt->name); | ||
| 341 | return 0; | ||
| 342 | } | ||
| 343 | break; | ||
| 344 | case range_option: | ||
| 345 | if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { | ||
| 346 | dev_info(&pdev->dev, "%s set to %i\n", opt->name, | ||
| 347 | *value); | ||
| 348 | return 0; | ||
| 349 | } | ||
| 350 | break; | ||
| 351 | case list_option:{ | ||
| 352 | int i; | ||
| 353 | struct atl1_opt_list *ent; | ||
| 354 | |||
| 355 | for (i = 0; i < opt->arg.l.nr; i++) { | ||
| 356 | ent = &opt->arg.l.p[i]; | ||
| 357 | if (*value == ent->i) { | ||
| 358 | if (ent->str[0] != '\0') | ||
| 359 | dev_info(&pdev->dev, "%s\n", | ||
| 360 | ent->str); | ||
| 361 | return 0; | ||
| 362 | } | ||
| 363 | } | ||
| 364 | } | ||
| 365 | break; | ||
| 366 | |||
| 367 | default: | ||
| 368 | break; | ||
| 369 | } | ||
| 370 | |||
| 371 | dev_info(&pdev->dev, "invalid %s specified (%i) %s\n", | ||
| 372 | opt->name, *value, opt->err); | ||
| 373 | *value = opt->def; | ||
| 374 | return -1; | ||
| 375 | } | ||
| 376 | |||
| 377 | /* | ||
| 378 | * atl1_check_options - Range Checking for Command Line Parameters | ||
| 379 | * @adapter: board private structure | ||
| 380 | * | ||
| 381 | * This routine checks all command line parameters for valid user | ||
| 382 | * input. If an invalid value is given, or if no user specified | ||
| 383 | * value exists, a default value is used. The final value is stored | ||
| 384 | * in a variable in the adapter structure. | ||
| 385 | */ | ||
| 386 | void __devinit atl1_check_options(struct atl1_adapter *adapter) | ||
| 387 | { | ||
| 388 | struct pci_dev *pdev = adapter->pdev; | ||
| 389 | int bd = adapter->bd_number; | ||
| 390 | if (bd >= ATL1_MAX_NIC) { | ||
| 391 | dev_notice(&pdev->dev, "no configuration for board#%i\n", bd); | ||
| 392 | dev_notice(&pdev->dev, "using defaults for all values\n"); | ||
| 393 | } | ||
| 394 | { /* Interrupt Moderate Timer */ | ||
| 395 | struct atl1_option opt = { | ||
| 396 | .type = range_option, | ||
| 397 | .name = "Interrupt Moderator Timer", | ||
| 398 | .err = "using default of " | ||
| 399 | __MODULE_STRING(DEFAULT_INT_MOD_CNT), | ||
| 400 | .def = DEFAULT_INT_MOD_CNT, | ||
| 401 | .arg = {.r = {.min = MIN_INT_MOD_CNT, | ||
| 402 | .max = MAX_INT_MOD_CNT} } | ||
| 403 | }; | ||
| 404 | int val; | ||
| 405 | if (num_int_mod_timer > bd) { | ||
| 406 | val = int_mod_timer[bd]; | ||
| 407 | atl1_validate_option(&val, &opt, pdev); | ||
| 408 | adapter->imt = (u16) val; | ||
| 409 | } else | ||
| 410 | adapter->imt = (u16) (opt.def); | ||
| 411 | } | ||
| 412 | |||
| 413 | { /* Flash Vendor */ | ||
| 414 | struct atl1_option opt = { | ||
| 415 | .type = range_option, | ||
| 416 | .name = "SPI Flash Vendor", | ||
| 417 | .err = "using default of " | ||
| 418 | __MODULE_STRING(FLASH_VENDOR_DEFAULT), | ||
| 419 | .def = DEFAULT_INT_MOD_CNT, | ||
| 420 | .arg = {.r = {.min = FLASH_VENDOR_MIN, | ||
| 421 | .max = FLASH_VENDOR_MAX} } | ||
| 422 | }; | ||
| 423 | int val; | ||
| 424 | if (num_flash_vendor > bd) { | ||
| 425 | val = flash_vendor[bd]; | ||
| 426 | atl1_validate_option(&val, &opt, pdev); | ||
| 427 | adapter->hw.flash_vendor = (u8) val; | ||
| 428 | } else | ||
| 429 | adapter->hw.flash_vendor = (u8) (opt.def); | ||
| 430 | } | ||
| 431 | } | ||
| 432 | |||
| 433 | #endif /* ATLX_C */ | 256 | #endif /* ATLX_C */ |
diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c index 194949afacd0..0b4adf4a0f7d 100644 --- a/drivers/net/ax88796.c +++ b/drivers/net/ax88796.c | |||
| @@ -1005,3 +1005,4 @@ module_exit(axdrv_exit); | |||
| 1005 | MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver"); | 1005 | MODULE_DESCRIPTION("AX88796 10/100 Ethernet platform driver"); |
| 1006 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); | 1006 | MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>"); |
| 1007 | MODULE_LICENSE("GPL v2"); | 1007 | MODULE_LICENSE("GPL v2"); |
| 1008 | MODULE_ALIAS("platform:ax88796"); | ||
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 717dcc1aa1e9..4fec8581bfd7 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c | |||
| @@ -47,6 +47,7 @@ | |||
| 47 | MODULE_AUTHOR(DRV_AUTHOR); | 47 | MODULE_AUTHOR(DRV_AUTHOR); |
| 48 | MODULE_LICENSE("GPL"); | 48 | MODULE_LICENSE("GPL"); |
| 49 | MODULE_DESCRIPTION(DRV_DESC); | 49 | MODULE_DESCRIPTION(DRV_DESC); |
| 50 | MODULE_ALIAS("platform:bfin_mac"); | ||
| 50 | 51 | ||
| 51 | #if defined(CONFIG_BFIN_MAC_USE_L1) | 52 | #if defined(CONFIG_BFIN_MAC_USE_L1) |
| 52 | # define bfin_mac_alloc(dma_handle, size) l1_data_sram_zalloc(size) | 53 | # define bfin_mac_alloc(dma_handle, size) l1_data_sram_zalloc(size) |
| @@ -1089,8 +1090,9 @@ static struct platform_driver bfin_mac_driver = { | |||
| 1089 | .resume = bfin_mac_resume, | 1090 | .resume = bfin_mac_resume, |
| 1090 | .suspend = bfin_mac_suspend, | 1091 | .suspend = bfin_mac_suspend, |
| 1091 | .driver = { | 1092 | .driver = { |
| 1092 | .name = DRV_NAME, | 1093 | .name = DRV_NAME, |
| 1093 | }, | 1094 | .owner = THIS_MODULE, |
| 1095 | }, | ||
| 1094 | }; | 1096 | }; |
| 1095 | 1097 | ||
| 1096 | static int __init bfin_mac_init(void) | 1098 | static int __init bfin_mac_init(void) |
| @@ -1106,3 +1108,4 @@ static void __exit bfin_mac_cleanup(void) | |||
| 1106 | } | 1108 | } |
| 1107 | 1109 | ||
| 1108 | module_exit(bfin_mac_cleanup); | 1110 | module_exit(bfin_mac_cleanup); |
| 1111 | |||
diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index 9da7ff437031..2b5740b3d182 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c | |||
| @@ -42,6 +42,7 @@ | |||
| 42 | MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>"); | 42 | MODULE_AUTHOR("Eugene Konev <ejka@imfi.kspu.ru>"); |
| 43 | MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)"); | 43 | MODULE_DESCRIPTION("TI AR7 ethernet driver (CPMAC)"); |
| 44 | MODULE_LICENSE("GPL"); | 44 | MODULE_LICENSE("GPL"); |
| 45 | MODULE_ALIAS("platform:cpmac"); | ||
| 45 | 46 | ||
| 46 | static int debug_level = 8; | 47 | static int debug_level = 8; |
| 47 | static int dumb_switch; | 48 | static int dumb_switch; |
| @@ -1103,6 +1104,7 @@ static int __devexit cpmac_remove(struct platform_device *pdev) | |||
| 1103 | 1104 | ||
| 1104 | static struct platform_driver cpmac_driver = { | 1105 | static struct platform_driver cpmac_driver = { |
| 1105 | .driver.name = "cpmac", | 1106 | .driver.name = "cpmac", |
| 1107 | .driver.owner = THIS_MODULE, | ||
| 1106 | .probe = cpmac_probe, | 1108 | .probe = cpmac_probe, |
| 1107 | .remove = __devexit_p(cpmac_remove), | 1109 | .remove = __devexit_p(cpmac_remove), |
| 1108 | }; | 1110 | }; |
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index d63cc93f055d..e6fe2614ea6d 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c | |||
| @@ -1418,3 +1418,4 @@ module_exit(dm9000_cleanup); | |||
| 1418 | MODULE_AUTHOR("Sascha Hauer, Ben Dooks"); | 1418 | MODULE_AUTHOR("Sascha Hauer, Ben Dooks"); |
| 1419 | MODULE_DESCRIPTION("Davicom DM9000 network driver"); | 1419 | MODULE_DESCRIPTION("Davicom DM9000 network driver"); |
| 1420 | MODULE_LICENSE("GPL"); | 1420 | MODULE_LICENSE("GPL"); |
| 1421 | MODULE_ALIAS("platform:dm9000"); | ||
diff --git a/drivers/net/e1000e/82571.c b/drivers/net/e1000e/82571.c index 01c88664bad3..462351ca2c81 100644 --- a/drivers/net/e1000e/82571.c +++ b/drivers/net/e1000e/82571.c | |||
| @@ -1326,12 +1326,10 @@ struct e1000_info e1000_82571_info = { | |||
| 1326 | .mac = e1000_82571, | 1326 | .mac = e1000_82571, |
| 1327 | .flags = FLAG_HAS_HW_VLAN_FILTER | 1327 | .flags = FLAG_HAS_HW_VLAN_FILTER |
| 1328 | | FLAG_HAS_JUMBO_FRAMES | 1328 | | FLAG_HAS_JUMBO_FRAMES |
| 1329 | | FLAG_HAS_STATS_PTC_PRC | ||
| 1330 | | FLAG_HAS_WOL | 1329 | | FLAG_HAS_WOL |
| 1331 | | FLAG_APME_IN_CTRL3 | 1330 | | FLAG_APME_IN_CTRL3 |
| 1332 | | FLAG_RX_CSUM_ENABLED | 1331 | | FLAG_RX_CSUM_ENABLED |
| 1333 | | FLAG_HAS_CTRLEXT_ON_LOAD | 1332 | | FLAG_HAS_CTRLEXT_ON_LOAD |
| 1334 | | FLAG_HAS_STATS_ICR_ICT | ||
| 1335 | | FLAG_HAS_SMART_POWER_DOWN | 1333 | | FLAG_HAS_SMART_POWER_DOWN |
| 1336 | | FLAG_RESET_OVERWRITES_LAA /* errata */ | 1334 | | FLAG_RESET_OVERWRITES_LAA /* errata */ |
| 1337 | | FLAG_TARC_SPEED_MODE_BIT /* errata */ | 1335 | | FLAG_TARC_SPEED_MODE_BIT /* errata */ |
| @@ -1347,12 +1345,10 @@ struct e1000_info e1000_82572_info = { | |||
| 1347 | .mac = e1000_82572, | 1345 | .mac = e1000_82572, |
| 1348 | .flags = FLAG_HAS_HW_VLAN_FILTER | 1346 | .flags = FLAG_HAS_HW_VLAN_FILTER |
| 1349 | | FLAG_HAS_JUMBO_FRAMES | 1347 | | FLAG_HAS_JUMBO_FRAMES |
| 1350 | | FLAG_HAS_STATS_PTC_PRC | ||
| 1351 | | FLAG_HAS_WOL | 1348 | | FLAG_HAS_WOL |
| 1352 | | FLAG_APME_IN_CTRL3 | 1349 | | FLAG_APME_IN_CTRL3 |
| 1353 | | FLAG_RX_CSUM_ENABLED | 1350 | | FLAG_RX_CSUM_ENABLED |
| 1354 | | FLAG_HAS_CTRLEXT_ON_LOAD | 1351 | | FLAG_HAS_CTRLEXT_ON_LOAD |
| 1355 | | FLAG_HAS_STATS_ICR_ICT | ||
| 1356 | | FLAG_TARC_SPEED_MODE_BIT, /* errata */ | 1352 | | FLAG_TARC_SPEED_MODE_BIT, /* errata */ |
| 1357 | .pba = 38, | 1353 | .pba = 38, |
| 1358 | .get_variants = e1000_get_variants_82571, | 1354 | .get_variants = e1000_get_variants_82571, |
| @@ -1365,11 +1361,9 @@ struct e1000_info e1000_82573_info = { | |||
| 1365 | .mac = e1000_82573, | 1361 | .mac = e1000_82573, |
| 1366 | .flags = FLAG_HAS_HW_VLAN_FILTER | 1362 | .flags = FLAG_HAS_HW_VLAN_FILTER |
| 1367 | | FLAG_HAS_JUMBO_FRAMES | 1363 | | FLAG_HAS_JUMBO_FRAMES |
| 1368 | | FLAG_HAS_STATS_PTC_PRC | ||
| 1369 | | FLAG_HAS_WOL | 1364 | | FLAG_HAS_WOL |
| 1370 | | FLAG_APME_IN_CTRL3 | 1365 | | FLAG_APME_IN_CTRL3 |
| 1371 | | FLAG_RX_CSUM_ENABLED | 1366 | | FLAG_RX_CSUM_ENABLED |
| 1372 | | FLAG_HAS_STATS_ICR_ICT | ||
| 1373 | | FLAG_HAS_SMART_POWER_DOWN | 1367 | | FLAG_HAS_SMART_POWER_DOWN |
| 1374 | | FLAG_HAS_AMT | 1368 | | FLAG_HAS_AMT |
| 1375 | | FLAG_HAS_ERT | 1369 | | FLAG_HAS_ERT |
diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index 572cfd44397a..2a53875cddbf 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h | |||
| @@ -184,6 +184,7 @@ | |||
| 184 | #define E1000_SWFW_EEP_SM 0x1 | 184 | #define E1000_SWFW_EEP_SM 0x1 |
| 185 | #define E1000_SWFW_PHY0_SM 0x2 | 185 | #define E1000_SWFW_PHY0_SM 0x2 |
| 186 | #define E1000_SWFW_PHY1_SM 0x4 | 186 | #define E1000_SWFW_PHY1_SM 0x4 |
| 187 | #define E1000_SWFW_CSR_SM 0x8 | ||
| 187 | 188 | ||
| 188 | /* Device Control */ | 189 | /* Device Control */ |
| 189 | #define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ | 190 | #define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ |
| @@ -527,8 +528,10 @@ | |||
| 527 | #define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ | 528 | #define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ |
| 528 | #define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ | 529 | #define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ |
| 529 | #define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ | 530 | #define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ |
| 531 | #define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */ | ||
| 530 | #define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ | 532 | #define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ |
| 531 | #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ | 533 | #define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ |
| 534 | #define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ | ||
| 532 | 535 | ||
| 533 | /* NVM Control */ | 536 | /* NVM Control */ |
| 534 | #define E1000_EECD_SK 0x00000001 /* NVM Clock */ | 537 | #define E1000_EECD_SK 0x00000001 /* NVM Clock */ |
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 5a89dff52264..38bfd0d261fe 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h | |||
| @@ -64,11 +64,14 @@ struct e1000_info; | |||
| 64 | /* Tx/Rx descriptor defines */ | 64 | /* Tx/Rx descriptor defines */ |
| 65 | #define E1000_DEFAULT_TXD 256 | 65 | #define E1000_DEFAULT_TXD 256 |
| 66 | #define E1000_MAX_TXD 4096 | 66 | #define E1000_MAX_TXD 4096 |
| 67 | #define E1000_MIN_TXD 80 | 67 | #define E1000_MIN_TXD 64 |
| 68 | 68 | ||
| 69 | #define E1000_DEFAULT_RXD 256 | 69 | #define E1000_DEFAULT_RXD 256 |
| 70 | #define E1000_MAX_RXD 4096 | 70 | #define E1000_MAX_RXD 4096 |
| 71 | #define E1000_MIN_RXD 80 | 71 | #define E1000_MIN_RXD 64 |
| 72 | |||
| 73 | #define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */ | ||
| 74 | #define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */ | ||
| 72 | 75 | ||
| 73 | /* Early Receive defines */ | 76 | /* Early Receive defines */ |
| 74 | #define E1000_ERT_2048 0x100 | 77 | #define E1000_ERT_2048 0x100 |
| @@ -147,6 +150,18 @@ struct e1000_ring { | |||
| 147 | struct e1000_queue_stats stats; | 150 | struct e1000_queue_stats stats; |
| 148 | }; | 151 | }; |
| 149 | 152 | ||
| 153 | /* PHY register snapshot values */ | ||
| 154 | struct e1000_phy_regs { | ||
| 155 | u16 bmcr; /* basic mode control register */ | ||
| 156 | u16 bmsr; /* basic mode status register */ | ||
| 157 | u16 advertise; /* auto-negotiation advertisement */ | ||
| 158 | u16 lpa; /* link partner ability register */ | ||
| 159 | u16 expansion; /* auto-negotiation expansion reg */ | ||
| 160 | u16 ctrl1000; /* 1000BASE-T control register */ | ||
| 161 | u16 stat1000; /* 1000BASE-T status register */ | ||
| 162 | u16 estatus; /* extended status register */ | ||
| 163 | }; | ||
| 164 | |||
| 150 | /* board specific private data structure */ | 165 | /* board specific private data structure */ |
| 151 | struct e1000_adapter { | 166 | struct e1000_adapter { |
| 152 | struct timer_list watchdog_timer; | 167 | struct timer_list watchdog_timer; |
| @@ -202,8 +217,8 @@ struct e1000_adapter { | |||
| 202 | /* Tx stats */ | 217 | /* Tx stats */ |
| 203 | u64 tpt_old; | 218 | u64 tpt_old; |
| 204 | u64 colc_old; | 219 | u64 colc_old; |
| 205 | u64 gotcl_old; | 220 | u32 gotc; |
| 206 | u32 gotcl; | 221 | u64 gotc_old; |
| 207 | u32 tx_timeout_count; | 222 | u32 tx_timeout_count; |
| 208 | u32 tx_fifo_head; | 223 | u32 tx_fifo_head; |
| 209 | u32 tx_head_addr; | 224 | u32 tx_head_addr; |
| @@ -227,8 +242,8 @@ struct e1000_adapter { | |||
| 227 | u64 hw_csum_err; | 242 | u64 hw_csum_err; |
| 228 | u64 hw_csum_good; | 243 | u64 hw_csum_good; |
| 229 | u64 rx_hdr_split; | 244 | u64 rx_hdr_split; |
| 230 | u64 gorcl_old; | 245 | u32 gorc; |
| 231 | u32 gorcl; | 246 | u64 gorc_old; |
| 232 | u32 alloc_rx_buff_failed; | 247 | u32 alloc_rx_buff_failed; |
| 233 | u32 rx_dma_failed; | 248 | u32 rx_dma_failed; |
| 234 | 249 | ||
| @@ -250,6 +265,9 @@ struct e1000_adapter { | |||
| 250 | struct e1000_phy_info phy_info; | 265 | struct e1000_phy_info phy_info; |
| 251 | struct e1000_phy_stats phy_stats; | 266 | struct e1000_phy_stats phy_stats; |
| 252 | 267 | ||
| 268 | /* Snapshot of PHY registers */ | ||
| 269 | struct e1000_phy_regs phy_regs; | ||
| 270 | |||
| 253 | struct e1000_ring test_tx_ring; | 271 | struct e1000_ring test_tx_ring; |
| 254 | struct e1000_ring test_rx_ring; | 272 | struct e1000_ring test_rx_ring; |
| 255 | u32 test_icr; | 273 | u32 test_icr; |
| @@ -286,8 +304,6 @@ struct e1000_info { | |||
| 286 | #define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5) | 304 | #define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5) |
| 287 | #define FLAG_HAS_SWSM_ON_LOAD (1 << 6) | 305 | #define FLAG_HAS_SWSM_ON_LOAD (1 << 6) |
| 288 | #define FLAG_HAS_JUMBO_FRAMES (1 << 7) | 306 | #define FLAG_HAS_JUMBO_FRAMES (1 << 7) |
| 289 | #define FLAG_HAS_STATS_ICR_ICT (1 << 9) | ||
| 290 | #define FLAG_HAS_STATS_PTC_PRC (1 << 10) | ||
| 291 | #define FLAG_HAS_SMART_POWER_DOWN (1 << 11) | 307 | #define FLAG_HAS_SMART_POWER_DOWN (1 << 11) |
| 292 | #define FLAG_IS_QUAD_PORT_A (1 << 12) | 308 | #define FLAG_IS_QUAD_PORT_A (1 << 12) |
| 293 | #define FLAG_IS_QUAD_PORT (1 << 13) | 309 | #define FLAG_IS_QUAD_PORT (1 << 13) |
| @@ -433,6 +449,8 @@ extern s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); | |||
| 433 | extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, | 449 | extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, |
| 434 | u32 usec_interval, bool *success); | 450 | u32 usec_interval, bool *success); |
| 435 | extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw); | 451 | extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw); |
| 452 | extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); | ||
| 453 | extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); | ||
| 436 | extern s32 e1000e_check_downshift(struct e1000_hw *hw); | 454 | extern s32 e1000e_check_downshift(struct e1000_hw *hw); |
| 437 | 455 | ||
| 438 | static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw) | 456 | static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw) |
diff --git a/drivers/net/e1000e/es2lan.c b/drivers/net/e1000e/es2lan.c index d59a99ae44be..dc552d7d6fac 100644 --- a/drivers/net/e1000e/es2lan.c +++ b/drivers/net/e1000e/es2lan.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | #define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL 0x00 | 41 | #define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL 0x00 |
| 42 | #define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL 0x02 | 42 | #define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL 0x02 |
| 43 | #define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL 0x10 | 43 | #define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL 0x10 |
| 44 | #define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE 0x1F | ||
| 44 | 45 | ||
| 45 | #define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS 0x0008 | 46 | #define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS 0x0008 |
| 46 | #define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS 0x0800 | 47 | #define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS 0x0800 |
| @@ -48,6 +49,7 @@ | |||
| 48 | 49 | ||
| 49 | #define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004 | 50 | #define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004 |
| 50 | #define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000 | 51 | #define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000 |
| 52 | #define E1000_KMRNCTRLSTA_OPMODE_E_IDLE 0x2000 | ||
| 51 | 53 | ||
| 52 | #define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */ | 54 | #define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */ |
| 53 | #define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000 | 55 | #define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000 |
| @@ -85,6 +87,9 @@ | |||
| 85 | /* Kumeran Mode Control Register (Page 193, Register 16) */ | 87 | /* Kumeran Mode Control Register (Page 193, Register 16) */ |
| 86 | #define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800 | 88 | #define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800 |
| 87 | 89 | ||
| 90 | /* Max number of times Kumeran read/write should be validated */ | ||
| 91 | #define GG82563_MAX_KMRN_RETRY 0x5 | ||
| 92 | |||
| 88 | /* Power Management Control Register (Page 193, Register 20) */ | 93 | /* Power Management Control Register (Page 193, Register 20) */ |
| 89 | #define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001 | 94 | #define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001 |
| 90 | /* 1=Enable SERDES Electrical Idle */ | 95 | /* 1=Enable SERDES Electrical Idle */ |
| @@ -270,6 +275,7 @@ static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw) | |||
| 270 | u16 mask; | 275 | u16 mask; |
| 271 | 276 | ||
| 272 | mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; | 277 | mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; |
| 278 | mask |= E1000_SWFW_CSR_SM; | ||
| 273 | 279 | ||
| 274 | return e1000_acquire_swfw_sync_80003es2lan(hw, mask); | 280 | return e1000_acquire_swfw_sync_80003es2lan(hw, mask); |
| 275 | } | 281 | } |
| @@ -286,6 +292,8 @@ static void e1000_release_phy_80003es2lan(struct e1000_hw *hw) | |||
| 286 | u16 mask; | 292 | u16 mask; |
| 287 | 293 | ||
| 288 | mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; | 294 | mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; |
| 295 | mask |= E1000_SWFW_CSR_SM; | ||
| 296 | |||
| 289 | e1000_release_swfw_sync_80003es2lan(hw, mask); | 297 | e1000_release_swfw_sync_80003es2lan(hw, mask); |
| 290 | } | 298 | } |
| 291 | 299 | ||
| @@ -410,20 +418,27 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, | |||
| 410 | u32 page_select; | 418 | u32 page_select; |
| 411 | u16 temp; | 419 | u16 temp; |
| 412 | 420 | ||
| 421 | ret_val = e1000_acquire_phy_80003es2lan(hw); | ||
| 422 | if (ret_val) | ||
| 423 | return ret_val; | ||
| 424 | |||
| 413 | /* Select Configuration Page */ | 425 | /* Select Configuration Page */ |
| 414 | if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) | 426 | if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { |
| 415 | page_select = GG82563_PHY_PAGE_SELECT; | 427 | page_select = GG82563_PHY_PAGE_SELECT; |
| 416 | else | 428 | } else { |
| 417 | /* | 429 | /* |
| 418 | * Use Alternative Page Select register to access | 430 | * Use Alternative Page Select register to access |
| 419 | * registers 30 and 31 | 431 | * registers 30 and 31 |
| 420 | */ | 432 | */ |
| 421 | page_select = GG82563_PHY_PAGE_SELECT_ALT; | 433 | page_select = GG82563_PHY_PAGE_SELECT_ALT; |
| 434 | } | ||
| 422 | 435 | ||
| 423 | temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); | 436 | temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); |
| 424 | ret_val = e1000e_write_phy_reg_m88(hw, page_select, temp); | 437 | ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp); |
| 425 | if (ret_val) | 438 | if (ret_val) { |
| 439 | e1000_release_phy_80003es2lan(hw); | ||
| 426 | return ret_val; | 440 | return ret_val; |
| 441 | } | ||
| 427 | 442 | ||
| 428 | /* | 443 | /* |
| 429 | * The "ready" bit in the MDIC register may be incorrectly set | 444 | * The "ready" bit in the MDIC register may be incorrectly set |
| @@ -433,20 +448,21 @@ static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, | |||
| 433 | udelay(200); | 448 | udelay(200); |
| 434 | 449 | ||
| 435 | /* ...and verify the command was successful. */ | 450 | /* ...and verify the command was successful. */ |
| 436 | ret_val = e1000e_read_phy_reg_m88(hw, page_select, &temp); | 451 | ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); |
| 437 | 452 | ||
| 438 | if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { | 453 | if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { |
| 439 | ret_val = -E1000_ERR_PHY; | 454 | ret_val = -E1000_ERR_PHY; |
| 455 | e1000_release_phy_80003es2lan(hw); | ||
| 440 | return ret_val; | 456 | return ret_val; |
| 441 | } | 457 | } |
| 442 | 458 | ||
| 443 | udelay(200); | 459 | udelay(200); |
| 444 | 460 | ||
| 445 | ret_val = e1000e_read_phy_reg_m88(hw, | 461 | ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, |
| 446 | MAX_PHY_REG_ADDRESS & offset, | 462 | data); |
| 447 | data); | ||
| 448 | 463 | ||
| 449 | udelay(200); | 464 | udelay(200); |
| 465 | e1000_release_phy_80003es2lan(hw); | ||
| 450 | 466 | ||
| 451 | return ret_val; | 467 | return ret_val; |
| 452 | } | 468 | } |
| @@ -467,20 +483,27 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, | |||
| 467 | u32 page_select; | 483 | u32 page_select; |
| 468 | u16 temp; | 484 | u16 temp; |
| 469 | 485 | ||
| 486 | ret_val = e1000_acquire_phy_80003es2lan(hw); | ||
| 487 | if (ret_val) | ||
| 488 | return ret_val; | ||
| 489 | |||
| 470 | /* Select Configuration Page */ | 490 | /* Select Configuration Page */ |
| 471 | if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) | 491 | if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { |
| 472 | page_select = GG82563_PHY_PAGE_SELECT; | 492 | page_select = GG82563_PHY_PAGE_SELECT; |
| 473 | else | 493 | } else { |
| 474 | /* | 494 | /* |
| 475 | * Use Alternative Page Select register to access | 495 | * Use Alternative Page Select register to access |
| 476 | * registers 30 and 31 | 496 | * registers 30 and 31 |
| 477 | */ | 497 | */ |
| 478 | page_select = GG82563_PHY_PAGE_SELECT_ALT; | 498 | page_select = GG82563_PHY_PAGE_SELECT_ALT; |
| 499 | } | ||
| 479 | 500 | ||
| 480 | temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); | 501 | temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); |
| 481 | ret_val = e1000e_write_phy_reg_m88(hw, page_select, temp); | 502 | ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp); |
| 482 | if (ret_val) | 503 | if (ret_val) { |
| 504 | e1000_release_phy_80003es2lan(hw); | ||
| 483 | return ret_val; | 505 | return ret_val; |
| 506 | } | ||
| 484 | 507 | ||
| 485 | 508 | ||
| 486 | /* | 509 | /* |
| @@ -491,18 +514,20 @@ static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, | |||
| 491 | udelay(200); | 514 | udelay(200); |
| 492 | 515 | ||
| 493 | /* ...and verify the command was successful. */ | 516 | /* ...and verify the command was successful. */ |
| 494 | ret_val = e1000e_read_phy_reg_m88(hw, page_select, &temp); | 517 | ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); |
| 495 | 518 | ||
| 496 | if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) | 519 | if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { |
| 520 | e1000_release_phy_80003es2lan(hw); | ||
| 497 | return -E1000_ERR_PHY; | 521 | return -E1000_ERR_PHY; |
| 522 | } | ||
| 498 | 523 | ||
| 499 | udelay(200); | 524 | udelay(200); |
| 500 | 525 | ||
| 501 | ret_val = e1000e_write_phy_reg_m88(hw, | 526 | ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, |
| 502 | MAX_PHY_REG_ADDRESS & offset, | 527 | data); |
| 503 | data); | ||
| 504 | 528 | ||
| 505 | udelay(200); | 529 | udelay(200); |
| 530 | e1000_release_phy_80003es2lan(hw); | ||
| 506 | 531 | ||
| 507 | return ret_val; | 532 | return ret_val; |
| 508 | } | 533 | } |
| @@ -882,10 +907,10 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) | |||
| 882 | struct e1000_phy_info *phy = &hw->phy; | 907 | struct e1000_phy_info *phy = &hw->phy; |
| 883 | s32 ret_val; | 908 | s32 ret_val; |
| 884 | u32 ctrl_ext; | 909 | u32 ctrl_ext; |
| 885 | u16 data; | 910 | u32 i = 0; |
| 911 | u16 data, data2; | ||
| 886 | 912 | ||
| 887 | ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, | 913 | ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &data); |
| 888 | &data); | ||
| 889 | if (ret_val) | 914 | if (ret_val) |
| 890 | return ret_val; | 915 | return ret_val; |
| 891 | 916 | ||
| @@ -893,8 +918,7 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) | |||
| 893 | /* Use 25MHz for both link down and 1000Base-T for Tx clock. */ | 918 | /* Use 25MHz for both link down and 1000Base-T for Tx clock. */ |
| 894 | data |= GG82563_MSCR_TX_CLK_1000MBPS_25; | 919 | data |= GG82563_MSCR_TX_CLK_1000MBPS_25; |
| 895 | 920 | ||
| 896 | ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, | 921 | ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, data); |
| 897 | data); | ||
| 898 | if (ret_val) | 922 | if (ret_val) |
| 899 | return ret_val; | 923 | return ret_val; |
| 900 | 924 | ||
| @@ -954,6 +978,18 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) | |||
| 954 | if (ret_val) | 978 | if (ret_val) |
| 955 | return ret_val; | 979 | return ret_val; |
| 956 | 980 | ||
| 981 | ret_val = e1000e_read_kmrn_reg(hw, | ||
| 982 | E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, | ||
| 983 | &data); | ||
| 984 | if (ret_val) | ||
| 985 | return ret_val; | ||
| 986 | data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE; | ||
| 987 | ret_val = e1000e_write_kmrn_reg(hw, | ||
| 988 | E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE, | ||
| 989 | data); | ||
| 990 | if (ret_val) | ||
| 991 | return ret_val; | ||
| 992 | |||
| 957 | ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL_2, &data); | 993 | ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL_2, &data); |
| 958 | if (ret_val) | 994 | if (ret_val) |
| 959 | return ret_val; | 995 | return ret_val; |
| @@ -983,9 +1019,18 @@ static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) | |||
| 983 | if (ret_val) | 1019 | if (ret_val) |
| 984 | return ret_val; | 1020 | return ret_val; |
| 985 | 1021 | ||
| 986 | ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &data); | 1022 | do { |
| 987 | if (ret_val) | 1023 | ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, |
| 988 | return ret_val; | 1024 | &data); |
| 1025 | if (ret_val) | ||
| 1026 | return ret_val; | ||
| 1027 | |||
| 1028 | ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, | ||
| 1029 | &data2); | ||
| 1030 | if (ret_val) | ||
| 1031 | return ret_val; | ||
| 1032 | i++; | ||
| 1033 | } while ((data != data2) && (i < GG82563_MAX_KMRN_RETRY)); | ||
| 989 | 1034 | ||
| 990 | data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; | 1035 | data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; |
| 991 | ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, data); | 1036 | ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, data); |
| @@ -1074,7 +1119,8 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex) | |||
| 1074 | { | 1119 | { |
| 1075 | s32 ret_val; | 1120 | s32 ret_val; |
| 1076 | u32 tipg; | 1121 | u32 tipg; |
| 1077 | u16 reg_data; | 1122 | u32 i = 0; |
| 1123 | u16 reg_data, reg_data2; | ||
| 1078 | 1124 | ||
| 1079 | reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT; | 1125 | reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT; |
| 1080 | ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, | 1126 | ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, |
| @@ -1088,9 +1134,16 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex) | |||
| 1088 | tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN; | 1134 | tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN; |
| 1089 | ew32(TIPG, tipg); | 1135 | ew32(TIPG, tipg); |
| 1090 | 1136 | ||
| 1091 | ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data); | 1137 | do { |
| 1092 | if (ret_val) | 1138 | ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data); |
| 1093 | return ret_val; | 1139 | if (ret_val) |
| 1140 | return ret_val; | ||
| 1141 | |||
| 1142 | ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data2); | ||
| 1143 | if (ret_val) | ||
| 1144 | return ret_val; | ||
| 1145 | i++; | ||
| 1146 | } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); | ||
| 1094 | 1147 | ||
| 1095 | if (duplex == HALF_DUPLEX) | 1148 | if (duplex == HALF_DUPLEX) |
| 1096 | reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER; | 1149 | reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER; |
| @@ -1112,8 +1165,9 @@ static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex) | |||
| 1112 | static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw) | 1165 | static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw) |
| 1113 | { | 1166 | { |
| 1114 | s32 ret_val; | 1167 | s32 ret_val; |
| 1115 | u16 reg_data; | 1168 | u16 reg_data, reg_data2; |
| 1116 | u32 tipg; | 1169 | u32 tipg; |
| 1170 | u32 i = 0; | ||
| 1117 | 1171 | ||
| 1118 | reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT; | 1172 | reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT; |
| 1119 | ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, | 1173 | ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, |
| @@ -1127,9 +1181,16 @@ static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw) | |||
| 1127 | tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; | 1181 | tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; |
| 1128 | ew32(TIPG, tipg); | 1182 | ew32(TIPG, tipg); |
| 1129 | 1183 | ||
| 1130 | ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data); | 1184 | do { |
| 1131 | if (ret_val) | 1185 | ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data); |
| 1132 | return ret_val; | 1186 | if (ret_val) |
| 1187 | return ret_val; | ||
| 1188 | |||
| 1189 | ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data2); | ||
| 1190 | if (ret_val) | ||
| 1191 | return ret_val; | ||
| 1192 | i++; | ||
| 1193 | } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); | ||
| 1133 | 1194 | ||
| 1134 | reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; | 1195 | reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; |
| 1135 | ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); | 1196 | ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); |
| @@ -1231,12 +1292,10 @@ struct e1000_info e1000_es2_info = { | |||
| 1231 | .mac = e1000_80003es2lan, | 1292 | .mac = e1000_80003es2lan, |
| 1232 | .flags = FLAG_HAS_HW_VLAN_FILTER | 1293 | .flags = FLAG_HAS_HW_VLAN_FILTER |
| 1233 | | FLAG_HAS_JUMBO_FRAMES | 1294 | | FLAG_HAS_JUMBO_FRAMES |
| 1234 | | FLAG_HAS_STATS_PTC_PRC | ||
| 1235 | | FLAG_HAS_WOL | 1295 | | FLAG_HAS_WOL |
| 1236 | | FLAG_APME_IN_CTRL3 | 1296 | | FLAG_APME_IN_CTRL3 |
| 1237 | | FLAG_RX_CSUM_ENABLED | 1297 | | FLAG_RX_CSUM_ENABLED |
| 1238 | | FLAG_HAS_CTRLEXT_ON_LOAD | 1298 | | FLAG_HAS_CTRLEXT_ON_LOAD |
| 1239 | | FLAG_HAS_STATS_ICR_ICT | ||
| 1240 | | FLAG_RX_NEEDS_RESTART /* errata */ | 1299 | | FLAG_RX_NEEDS_RESTART /* errata */ |
| 1241 | | FLAG_TARC_SET_BIT_ZERO /* errata */ | 1300 | | FLAG_TARC_SET_BIT_ZERO /* errata */ |
| 1242 | | FLAG_APME_CHECK_PORT_B | 1301 | | FLAG_APME_CHECK_PORT_B |
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index 6d1b257bbda6..ce045acce63e 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c | |||
| @@ -46,8 +46,8 @@ struct e1000_stats { | |||
| 46 | static const struct e1000_stats e1000_gstrings_stats[] = { | 46 | static const struct e1000_stats e1000_gstrings_stats[] = { |
| 47 | { "rx_packets", E1000_STAT(stats.gprc) }, | 47 | { "rx_packets", E1000_STAT(stats.gprc) }, |
| 48 | { "tx_packets", E1000_STAT(stats.gptc) }, | 48 | { "tx_packets", E1000_STAT(stats.gptc) }, |
| 49 | { "rx_bytes", E1000_STAT(stats.gorcl) }, | 49 | { "rx_bytes", E1000_STAT(stats.gorc) }, |
| 50 | { "tx_bytes", E1000_STAT(stats.gotcl) }, | 50 | { "tx_bytes", E1000_STAT(stats.gotc) }, |
| 51 | { "rx_broadcast", E1000_STAT(stats.bprc) }, | 51 | { "rx_broadcast", E1000_STAT(stats.bprc) }, |
| 52 | { "tx_broadcast", E1000_STAT(stats.bptc) }, | 52 | { "tx_broadcast", E1000_STAT(stats.bptc) }, |
| 53 | { "rx_multicast", E1000_STAT(stats.mprc) }, | 53 | { "rx_multicast", E1000_STAT(stats.mprc) }, |
| @@ -83,7 +83,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = { | |||
| 83 | { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) }, | 83 | { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) }, |
| 84 | { "tx_flow_control_xon", E1000_STAT(stats.xontxc) }, | 84 | { "tx_flow_control_xon", E1000_STAT(stats.xontxc) }, |
| 85 | { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) }, | 85 | { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) }, |
| 86 | { "rx_long_byte_count", E1000_STAT(stats.gorcl) }, | 86 | { "rx_long_byte_count", E1000_STAT(stats.gorc) }, |
| 87 | { "rx_csum_offload_good", E1000_STAT(hw_csum_good) }, | 87 | { "rx_csum_offload_good", E1000_STAT(hw_csum_good) }, |
| 88 | { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }, | 88 | { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }, |
| 89 | { "rx_header_split", E1000_STAT(rx_hdr_split) }, | 89 | { "rx_header_split", E1000_STAT(rx_hdr_split) }, |
| @@ -1770,6 +1770,47 @@ static int e1000_phys_id(struct net_device *netdev, u32 data) | |||
| 1770 | return 0; | 1770 | return 0; |
| 1771 | } | 1771 | } |
| 1772 | 1772 | ||
| 1773 | static int e1000_get_coalesce(struct net_device *netdev, | ||
| 1774 | struct ethtool_coalesce *ec) | ||
| 1775 | { | ||
| 1776 | struct e1000_adapter *adapter = netdev_priv(netdev); | ||
| 1777 | |||
| 1778 | if (adapter->itr_setting <= 3) | ||
| 1779 | ec->rx_coalesce_usecs = adapter->itr_setting; | ||
| 1780 | else | ||
| 1781 | ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting; | ||
| 1782 | |||
| 1783 | return 0; | ||
| 1784 | } | ||
| 1785 | |||
| 1786 | static int e1000_set_coalesce(struct net_device *netdev, | ||
| 1787 | struct ethtool_coalesce *ec) | ||
| 1788 | { | ||
| 1789 | struct e1000_adapter *adapter = netdev_priv(netdev); | ||
| 1790 | struct e1000_hw *hw = &adapter->hw; | ||
| 1791 | |||
| 1792 | if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) || | ||
| 1793 | ((ec->rx_coalesce_usecs > 3) && | ||
| 1794 | (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) || | ||
| 1795 | (ec->rx_coalesce_usecs == 2)) | ||
| 1796 | return -EINVAL; | ||
| 1797 | |||
| 1798 | if (ec->rx_coalesce_usecs <= 3) { | ||
| 1799 | adapter->itr = 20000; | ||
| 1800 | adapter->itr_setting = ec->rx_coalesce_usecs; | ||
| 1801 | } else { | ||
| 1802 | adapter->itr = (1000000 / ec->rx_coalesce_usecs); | ||
| 1803 | adapter->itr_setting = adapter->itr & ~3; | ||
| 1804 | } | ||
| 1805 | |||
| 1806 | if (adapter->itr_setting != 0) | ||
| 1807 | ew32(ITR, 1000000000 / (adapter->itr * 256)); | ||
| 1808 | else | ||
| 1809 | ew32(ITR, 0); | ||
| 1810 | |||
| 1811 | return 0; | ||
| 1812 | } | ||
| 1813 | |||
| 1773 | static int e1000_nway_reset(struct net_device *netdev) | 1814 | static int e1000_nway_reset(struct net_device *netdev) |
| 1774 | { | 1815 | { |
| 1775 | struct e1000_adapter *adapter = netdev_priv(netdev); | 1816 | struct e1000_adapter *adapter = netdev_priv(netdev); |
| @@ -1845,6 +1886,8 @@ static const struct ethtool_ops e1000_ethtool_ops = { | |||
| 1845 | .phys_id = e1000_phys_id, | 1886 | .phys_id = e1000_phys_id, |
| 1846 | .get_ethtool_stats = e1000_get_ethtool_stats, | 1887 | .get_ethtool_stats = e1000_get_ethtool_stats, |
| 1847 | .get_sset_count = e1000e_get_sset_count, | 1888 | .get_sset_count = e1000e_get_sset_count, |
| 1889 | .get_coalesce = e1000_get_coalesce, | ||
| 1890 | .set_coalesce = e1000_set_coalesce, | ||
| 1848 | }; | 1891 | }; |
| 1849 | 1892 | ||
| 1850 | void e1000e_set_ethtool_ops(struct net_device *netdev) | 1893 | void e1000e_set_ethtool_ops(struct net_device *netdev) |
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h index 53f1ac6327fa..a930e6d9cf02 100644 --- a/drivers/net/e1000e/hw.h +++ b/drivers/net/e1000e/hw.h | |||
| @@ -592,10 +592,8 @@ struct e1000_hw_stats { | |||
| 592 | u64 bprc; | 592 | u64 bprc; |
| 593 | u64 mprc; | 593 | u64 mprc; |
| 594 | u64 gptc; | 594 | u64 gptc; |
| 595 | u64 gorcl; | 595 | u64 gorc; |
| 596 | u64 gorch; | 596 | u64 gotc; |
| 597 | u64 gotcl; | ||
| 598 | u64 gotch; | ||
| 599 | u64 rnbc; | 597 | u64 rnbc; |
| 600 | u64 ruc; | 598 | u64 ruc; |
| 601 | u64 rfc; | 599 | u64 rfc; |
| @@ -604,10 +602,8 @@ struct e1000_hw_stats { | |||
| 604 | u64 mgprc; | 602 | u64 mgprc; |
| 605 | u64 mgpdc; | 603 | u64 mgpdc; |
| 606 | u64 mgptc; | 604 | u64 mgptc; |
| 607 | u64 torl; | 605 | u64 tor; |
| 608 | u64 torh; | 606 | u64 tot; |
| 609 | u64 totl; | ||
| 610 | u64 toth; | ||
| 611 | u64 tpr; | 607 | u64 tpr; |
| 612 | u64 tpt; | 608 | u64 tpt; |
| 613 | u64 ptc64; | 609 | u64 ptc64; |
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index c8dc47fd132a..8991ab8911e2 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
| @@ -46,7 +46,7 @@ | |||
| 46 | 46 | ||
| 47 | #include "e1000.h" | 47 | #include "e1000.h" |
| 48 | 48 | ||
| 49 | #define DRV_VERSION "0.2.0" | 49 | #define DRV_VERSION "0.2.1" |
| 50 | char e1000e_driver_name[] = "e1000e"; | 50 | char e1000e_driver_name[] = "e1000e"; |
| 51 | const char e1000e_driver_version[] = DRV_VERSION; | 51 | const char e1000e_driver_version[] = DRV_VERSION; |
| 52 | 52 | ||
| @@ -466,10 +466,10 @@ next_desc: | |||
| 466 | if (cleaned_count) | 466 | if (cleaned_count) |
| 467 | adapter->alloc_rx_buf(adapter, cleaned_count); | 467 | adapter->alloc_rx_buf(adapter, cleaned_count); |
| 468 | 468 | ||
| 469 | adapter->total_rx_packets += total_rx_packets; | ||
| 470 | adapter->total_rx_bytes += total_rx_bytes; | 469 | adapter->total_rx_bytes += total_rx_bytes; |
| 471 | adapter->net_stats.rx_packets += total_rx_packets; | 470 | adapter->total_rx_packets += total_rx_packets; |
| 472 | adapter->net_stats.rx_bytes += total_rx_bytes; | 471 | adapter->net_stats.rx_bytes += total_rx_bytes; |
| 472 | adapter->net_stats.rx_packets += total_rx_packets; | ||
| 473 | return cleaned; | 473 | return cleaned; |
| 474 | } | 474 | } |
| 475 | 475 | ||
| @@ -606,8 +606,8 @@ static bool e1000_clean_tx_irq(struct e1000_adapter *adapter) | |||
| 606 | } | 606 | } |
| 607 | adapter->total_tx_bytes += total_tx_bytes; | 607 | adapter->total_tx_bytes += total_tx_bytes; |
| 608 | adapter->total_tx_packets += total_tx_packets; | 608 | adapter->total_tx_packets += total_tx_packets; |
| 609 | adapter->net_stats.tx_packets += total_tx_packets; | ||
| 610 | adapter->net_stats.tx_bytes += total_tx_bytes; | 609 | adapter->net_stats.tx_bytes += total_tx_bytes; |
| 610 | adapter->net_stats.tx_packets += total_tx_packets; | ||
| 611 | return cleaned; | 611 | return cleaned; |
| 612 | } | 612 | } |
| 613 | 613 | ||
| @@ -775,10 +775,10 @@ next_desc: | |||
| 775 | if (cleaned_count) | 775 | if (cleaned_count) |
| 776 | adapter->alloc_rx_buf(adapter, cleaned_count); | 776 | adapter->alloc_rx_buf(adapter, cleaned_count); |
| 777 | 777 | ||
| 778 | adapter->total_rx_packets += total_rx_packets; | ||
| 779 | adapter->total_rx_bytes += total_rx_bytes; | 778 | adapter->total_rx_bytes += total_rx_bytes; |
| 780 | adapter->net_stats.rx_packets += total_rx_packets; | 779 | adapter->total_rx_packets += total_rx_packets; |
| 781 | adapter->net_stats.rx_bytes += total_rx_bytes; | 780 | adapter->net_stats.rx_bytes += total_rx_bytes; |
| 781 | adapter->net_stats.rx_packets += total_rx_packets; | ||
| 782 | return cleaned; | 782 | return cleaned; |
| 783 | } | 783 | } |
| 784 | 784 | ||
| @@ -2506,56 +2506,27 @@ void e1000e_update_stats(struct e1000_adapter *adapter) | |||
| 2506 | 2506 | ||
| 2507 | adapter->stats.crcerrs += er32(CRCERRS); | 2507 | adapter->stats.crcerrs += er32(CRCERRS); |
| 2508 | adapter->stats.gprc += er32(GPRC); | 2508 | adapter->stats.gprc += er32(GPRC); |
| 2509 | adapter->stats.gorcl += er32(GORCL); | 2509 | adapter->stats.gorc += er32(GORCL); |
| 2510 | adapter->stats.gorch += er32(GORCH); | 2510 | er32(GORCH); /* Clear gorc */ |
| 2511 | adapter->stats.bprc += er32(BPRC); | 2511 | adapter->stats.bprc += er32(BPRC); |
| 2512 | adapter->stats.mprc += er32(MPRC); | 2512 | adapter->stats.mprc += er32(MPRC); |
| 2513 | adapter->stats.roc += er32(ROC); | 2513 | adapter->stats.roc += er32(ROC); |
| 2514 | 2514 | ||
| 2515 | if (adapter->flags & FLAG_HAS_STATS_PTC_PRC) { | ||
| 2516 | adapter->stats.prc64 += er32(PRC64); | ||
| 2517 | adapter->stats.prc127 += er32(PRC127); | ||
| 2518 | adapter->stats.prc255 += er32(PRC255); | ||
| 2519 | adapter->stats.prc511 += er32(PRC511); | ||
| 2520 | adapter->stats.prc1023 += er32(PRC1023); | ||
| 2521 | adapter->stats.prc1522 += er32(PRC1522); | ||
| 2522 | adapter->stats.symerrs += er32(SYMERRS); | ||
| 2523 | adapter->stats.sec += er32(SEC); | ||
| 2524 | } | ||
| 2525 | |||
| 2526 | adapter->stats.mpc += er32(MPC); | 2515 | adapter->stats.mpc += er32(MPC); |
| 2527 | adapter->stats.scc += er32(SCC); | 2516 | adapter->stats.scc += er32(SCC); |
| 2528 | adapter->stats.ecol += er32(ECOL); | 2517 | adapter->stats.ecol += er32(ECOL); |
| 2529 | adapter->stats.mcc += er32(MCC); | 2518 | adapter->stats.mcc += er32(MCC); |
| 2530 | adapter->stats.latecol += er32(LATECOL); | 2519 | adapter->stats.latecol += er32(LATECOL); |
| 2531 | adapter->stats.dc += er32(DC); | 2520 | adapter->stats.dc += er32(DC); |
| 2532 | adapter->stats.rlec += er32(RLEC); | ||
| 2533 | adapter->stats.xonrxc += er32(XONRXC); | 2521 | adapter->stats.xonrxc += er32(XONRXC); |
| 2534 | adapter->stats.xontxc += er32(XONTXC); | 2522 | adapter->stats.xontxc += er32(XONTXC); |
| 2535 | adapter->stats.xoffrxc += er32(XOFFRXC); | 2523 | adapter->stats.xoffrxc += er32(XOFFRXC); |
| 2536 | adapter->stats.xofftxc += er32(XOFFTXC); | 2524 | adapter->stats.xofftxc += er32(XOFFTXC); |
| 2537 | adapter->stats.fcruc += er32(FCRUC); | ||
| 2538 | adapter->stats.gptc += er32(GPTC); | 2525 | adapter->stats.gptc += er32(GPTC); |
| 2539 | adapter->stats.gotcl += er32(GOTCL); | 2526 | adapter->stats.gotc += er32(GOTCL); |
| 2540 | adapter->stats.gotch += er32(GOTCH); | 2527 | er32(GOTCH); /* Clear gotc */ |
| 2541 | adapter->stats.rnbc += er32(RNBC); | 2528 | adapter->stats.rnbc += er32(RNBC); |
| 2542 | adapter->stats.ruc += er32(RUC); | 2529 | adapter->stats.ruc += er32(RUC); |
| 2543 | adapter->stats.rfc += er32(RFC); | ||
| 2544 | adapter->stats.rjc += er32(RJC); | ||
| 2545 | adapter->stats.torl += er32(TORL); | ||
| 2546 | adapter->stats.torh += er32(TORH); | ||
| 2547 | adapter->stats.totl += er32(TOTL); | ||
| 2548 | adapter->stats.toth += er32(TOTH); | ||
| 2549 | adapter->stats.tpr += er32(TPR); | ||
| 2550 | |||
| 2551 | if (adapter->flags & FLAG_HAS_STATS_PTC_PRC) { | ||
| 2552 | adapter->stats.ptc64 += er32(PTC64); | ||
| 2553 | adapter->stats.ptc127 += er32(PTC127); | ||
| 2554 | adapter->stats.ptc255 += er32(PTC255); | ||
| 2555 | adapter->stats.ptc511 += er32(PTC511); | ||
| 2556 | adapter->stats.ptc1023 += er32(PTC1023); | ||
| 2557 | adapter->stats.ptc1522 += er32(PTC1522); | ||
| 2558 | } | ||
| 2559 | 2530 | ||
| 2560 | adapter->stats.mptc += er32(MPTC); | 2531 | adapter->stats.mptc += er32(MPTC); |
| 2561 | adapter->stats.bptc += er32(BPTC); | 2532 | adapter->stats.bptc += er32(BPTC); |
| @@ -2574,19 +2545,6 @@ void e1000e_update_stats(struct e1000_adapter *adapter) | |||
| 2574 | adapter->stats.tsctc += er32(TSCTC); | 2545 | adapter->stats.tsctc += er32(TSCTC); |
| 2575 | adapter->stats.tsctfc += er32(TSCTFC); | 2546 | adapter->stats.tsctfc += er32(TSCTFC); |
| 2576 | 2547 | ||
| 2577 | adapter->stats.iac += er32(IAC); | ||
| 2578 | |||
| 2579 | if (adapter->flags & FLAG_HAS_STATS_ICR_ICT) { | ||
| 2580 | adapter->stats.icrxoc += er32(ICRXOC); | ||
| 2581 | adapter->stats.icrxptc += er32(ICRXPTC); | ||
| 2582 | adapter->stats.icrxatc += er32(ICRXATC); | ||
| 2583 | adapter->stats.ictxptc += er32(ICTXPTC); | ||
| 2584 | adapter->stats.ictxatc += er32(ICTXATC); | ||
| 2585 | adapter->stats.ictxqec += er32(ICTXQEC); | ||
| 2586 | adapter->stats.ictxqmtc += er32(ICTXQMTC); | ||
| 2587 | adapter->stats.icrxdmtc += er32(ICRXDMTC); | ||
| 2588 | } | ||
| 2589 | |||
| 2590 | /* Fill out the OS statistics structure */ | 2548 | /* Fill out the OS statistics structure */ |
| 2591 | adapter->net_stats.multicast = adapter->stats.mprc; | 2549 | adapter->net_stats.multicast = adapter->stats.mprc; |
| 2592 | adapter->net_stats.collisions = adapter->stats.colc; | 2550 | adapter->net_stats.collisions = adapter->stats.colc; |
| @@ -2633,6 +2591,54 @@ void e1000e_update_stats(struct e1000_adapter *adapter) | |||
| 2633 | spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); | 2591 | spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); |
| 2634 | } | 2592 | } |
| 2635 | 2593 | ||
| 2594 | /** | ||
| 2595 | * e1000_phy_read_status - Update the PHY register status snapshot | ||
| 2596 | * @adapter: board private structure | ||
| 2597 | **/ | ||
| 2598 | static void e1000_phy_read_status(struct e1000_adapter *adapter) | ||
| 2599 | { | ||
| 2600 | struct e1000_hw *hw = &adapter->hw; | ||
| 2601 | struct e1000_phy_regs *phy = &adapter->phy_regs; | ||
| 2602 | int ret_val; | ||
| 2603 | unsigned long irq_flags; | ||
| 2604 | |||
| 2605 | |||
| 2606 | spin_lock_irqsave(&adapter->stats_lock, irq_flags); | ||
| 2607 | |||
| 2608 | if ((er32(STATUS) & E1000_STATUS_LU) && | ||
| 2609 | (adapter->hw.phy.media_type == e1000_media_type_copper)) { | ||
| 2610 | ret_val = e1e_rphy(hw, PHY_CONTROL, &phy->bmcr); | ||
| 2611 | ret_val |= e1e_rphy(hw, PHY_STATUS, &phy->bmsr); | ||
| 2612 | ret_val |= e1e_rphy(hw, PHY_AUTONEG_ADV, &phy->advertise); | ||
| 2613 | ret_val |= e1e_rphy(hw, PHY_LP_ABILITY, &phy->lpa); | ||
| 2614 | ret_val |= e1e_rphy(hw, PHY_AUTONEG_EXP, &phy->expansion); | ||
| 2615 | ret_val |= e1e_rphy(hw, PHY_1000T_CTRL, &phy->ctrl1000); | ||
| 2616 | ret_val |= e1e_rphy(hw, PHY_1000T_STATUS, &phy->stat1000); | ||
| 2617 | ret_val |= e1e_rphy(hw, PHY_EXT_STATUS, &phy->estatus); | ||
| 2618 | if (ret_val) | ||
| 2619 | ndev_warn(adapter->netdev, | ||
| 2620 | "Error reading PHY register\n"); | ||
| 2621 | } else { | ||
| 2622 | /* | ||
| 2623 | * Do not read PHY registers if link is not up | ||
| 2624 | * Set values to typical power-on defaults | ||
| 2625 | */ | ||
| 2626 | phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX); | ||
| 2627 | phy->bmsr = (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | | ||
| 2628 | BMSR_10HALF | BMSR_ESTATEN | BMSR_ANEGCAPABLE | | ||
| 2629 | BMSR_ERCAP); | ||
| 2630 | phy->advertise = (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP | | ||
| 2631 | ADVERTISE_ALL | ADVERTISE_CSMA); | ||
| 2632 | phy->lpa = 0; | ||
| 2633 | phy->expansion = EXPANSION_ENABLENPAGE; | ||
| 2634 | phy->ctrl1000 = ADVERTISE_1000FULL; | ||
| 2635 | phy->stat1000 = 0; | ||
| 2636 | phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF); | ||
| 2637 | } | ||
| 2638 | |||
| 2639 | spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); | ||
| 2640 | } | ||
| 2641 | |||
| 2636 | static void e1000_print_link_info(struct e1000_adapter *adapter) | 2642 | static void e1000_print_link_info(struct e1000_adapter *adapter) |
| 2637 | { | 2643 | { |
| 2638 | struct e1000_hw *hw = &adapter->hw; | 2644 | struct e1000_hw *hw = &adapter->hw; |
| @@ -2745,6 +2751,7 @@ static void e1000_watchdog_task(struct work_struct *work) | |||
| 2745 | if (!netif_carrier_ok(netdev)) { | 2751 | if (!netif_carrier_ok(netdev)) { |
| 2746 | bool txb2b = 1; | 2752 | bool txb2b = 1; |
| 2747 | /* update snapshot of PHY registers on LSC */ | 2753 | /* update snapshot of PHY registers on LSC */ |
| 2754 | e1000_phy_read_status(adapter); | ||
| 2748 | mac->ops.get_link_up_info(&adapter->hw, | 2755 | mac->ops.get_link_up_info(&adapter->hw, |
| 2749 | &adapter->link_speed, | 2756 | &adapter->link_speed, |
| 2750 | &adapter->link_duplex); | 2757 | &adapter->link_duplex); |
| @@ -2842,10 +2849,10 @@ link_up: | |||
| 2842 | mac->collision_delta = adapter->stats.colc - adapter->colc_old; | 2849 | mac->collision_delta = adapter->stats.colc - adapter->colc_old; |
| 2843 | adapter->colc_old = adapter->stats.colc; | 2850 | adapter->colc_old = adapter->stats.colc; |
| 2844 | 2851 | ||
| 2845 | adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old; | 2852 | adapter->gorc = adapter->stats.gorc - adapter->gorc_old; |
| 2846 | adapter->gorcl_old = adapter->stats.gorcl; | 2853 | adapter->gorc_old = adapter->stats.gorc; |
| 2847 | adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old; | 2854 | adapter->gotc = adapter->stats.gotc - adapter->gotc_old; |
| 2848 | adapter->gotcl_old = adapter->stats.gotcl; | 2855 | adapter->gotc_old = adapter->stats.gotc; |
| 2849 | 2856 | ||
| 2850 | e1000e_update_adaptive(&adapter->hw); | 2857 | e1000e_update_adaptive(&adapter->hw); |
| 2851 | 2858 | ||
| @@ -3500,7 +3507,6 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, | |||
| 3500 | { | 3507 | { |
| 3501 | struct e1000_adapter *adapter = netdev_priv(netdev); | 3508 | struct e1000_adapter *adapter = netdev_priv(netdev); |
| 3502 | struct mii_ioctl_data *data = if_mii(ifr); | 3509 | struct mii_ioctl_data *data = if_mii(ifr); |
| 3503 | unsigned long irq_flags; | ||
| 3504 | 3510 | ||
| 3505 | if (adapter->hw.phy.media_type != e1000_media_type_copper) | 3511 | if (adapter->hw.phy.media_type != e1000_media_type_copper) |
| 3506 | return -EOPNOTSUPP; | 3512 | return -EOPNOTSUPP; |
| @@ -3512,13 +3518,40 @@ static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, | |||
| 3512 | case SIOCGMIIREG: | 3518 | case SIOCGMIIREG: |
| 3513 | if (!capable(CAP_NET_ADMIN)) | 3519 | if (!capable(CAP_NET_ADMIN)) |
| 3514 | return -EPERM; | 3520 | return -EPERM; |
| 3515 | spin_lock_irqsave(&adapter->stats_lock, irq_flags); | 3521 | switch (data->reg_num & 0x1F) { |
| 3516 | if (e1e_rphy(&adapter->hw, data->reg_num & 0x1F, | 3522 | case MII_BMCR: |
| 3517 | &data->val_out)) { | 3523 | data->val_out = adapter->phy_regs.bmcr; |
| 3518 | spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); | 3524 | break; |
| 3525 | case MII_BMSR: | ||
| 3526 | data->val_out = adapter->phy_regs.bmsr; | ||
| 3527 | break; | ||
| 3528 | case MII_PHYSID1: | ||
| 3529 | data->val_out = (adapter->hw.phy.id >> 16); | ||
| 3530 | break; | ||
| 3531 | case MII_PHYSID2: | ||
| 3532 | data->val_out = (adapter->hw.phy.id & 0xFFFF); | ||
| 3533 | break; | ||
| 3534 | case MII_ADVERTISE: | ||
| 3535 | data->val_out = adapter->phy_regs.advertise; | ||
| 3536 | break; | ||
| 3537 | case MII_LPA: | ||
| 3538 | data->val_out = adapter->phy_regs.lpa; | ||
| 3539 | break; | ||
| 3540 | case MII_EXPANSION: | ||
| 3541 | data->val_out = adapter->phy_regs.expansion; | ||
| 3542 | break; | ||
| 3543 | case MII_CTRL1000: | ||
| 3544 | data->val_out = adapter->phy_regs.ctrl1000; | ||
| 3545 | break; | ||
| 3546 | case MII_STAT1000: | ||
| 3547 | data->val_out = adapter->phy_regs.stat1000; | ||
| 3548 | break; | ||
| 3549 | case MII_ESTATUS: | ||
| 3550 | data->val_out = adapter->phy_regs.estatus; | ||
| 3551 | break; | ||
| 3552 | default: | ||
| 3519 | return -EIO; | 3553 | return -EIO; |
| 3520 | } | 3554 | } |
| 3521 | spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); | ||
| 3522 | break; | 3555 | break; |
| 3523 | case SIOCSMIIREG: | 3556 | case SIOCSMIIREG: |
| 3524 | default: | 3557 | default: |
| @@ -3774,6 +3807,7 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) | |||
| 3774 | return PCI_ERS_RESULT_DISCONNECT; | 3807 | return PCI_ERS_RESULT_DISCONNECT; |
| 3775 | } | 3808 | } |
| 3776 | pci_set_master(pdev); | 3809 | pci_set_master(pdev); |
| 3810 | pci_restore_state(pdev); | ||
| 3777 | 3811 | ||
| 3778 | pci_enable_wake(pdev, PCI_D3hot, 0); | 3812 | pci_enable_wake(pdev, PCI_D3hot, 0); |
| 3779 | pci_enable_wake(pdev, PCI_D3cold, 0); | 3813 | pci_enable_wake(pdev, PCI_D3cold, 0); |
| @@ -3900,6 +3934,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
| 3900 | goto err_pci_reg; | 3934 | goto err_pci_reg; |
| 3901 | 3935 | ||
| 3902 | pci_set_master(pdev); | 3936 | pci_set_master(pdev); |
| 3937 | pci_save_state(pdev); | ||
| 3903 | 3938 | ||
| 3904 | err = -ENOMEM; | 3939 | err = -ENOMEM; |
| 3905 | netdev = alloc_etherdev(sizeof(struct e1000_adapter)); | 3940 | netdev = alloc_etherdev(sizeof(struct e1000_adapter)); |
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c index 3a4574caa75b..e102332a6bee 100644 --- a/drivers/net/e1000e/phy.c +++ b/drivers/net/e1000e/phy.c | |||
| @@ -116,7 +116,7 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw) | |||
| 116 | } | 116 | } |
| 117 | 117 | ||
| 118 | /** | 118 | /** |
| 119 | * e1000_read_phy_reg_mdic - Read MDI control register | 119 | * e1000e_read_phy_reg_mdic - Read MDI control register |
| 120 | * @hw: pointer to the HW structure | 120 | * @hw: pointer to the HW structure |
| 121 | * @offset: register offset to be read | 121 | * @offset: register offset to be read |
| 122 | * @data: pointer to the read data | 122 | * @data: pointer to the read data |
| @@ -124,7 +124,7 @@ s32 e1000e_phy_reset_dsp(struct e1000_hw *hw) | |||
| 124 | * Reads the MDI control register in the PHY at offset and stores the | 124 | * Reads the MDI control register in the PHY at offset and stores the |
| 125 | * information read to data. | 125 | * information read to data. |
| 126 | **/ | 126 | **/ |
| 127 | static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) | 127 | s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) |
| 128 | { | 128 | { |
| 129 | struct e1000_phy_info *phy = &hw->phy; | 129 | struct e1000_phy_info *phy = &hw->phy; |
| 130 | u32 i, mdic = 0; | 130 | u32 i, mdic = 0; |
| @@ -150,7 +150,7 @@ static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) | |||
| 150 | * Increasing the time out as testing showed failures with | 150 | * Increasing the time out as testing showed failures with |
| 151 | * the lower time out | 151 | * the lower time out |
| 152 | */ | 152 | */ |
| 153 | for (i = 0; i < 64; i++) { | 153 | for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { |
| 154 | udelay(50); | 154 | udelay(50); |
| 155 | mdic = er32(MDIC); | 155 | mdic = er32(MDIC); |
| 156 | if (mdic & E1000_MDIC_READY) | 156 | if (mdic & E1000_MDIC_READY) |
| @@ -170,14 +170,14 @@ static s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) | |||
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | /** | 172 | /** |
| 173 | * e1000_write_phy_reg_mdic - Write MDI control register | 173 | * e1000e_write_phy_reg_mdic - Write MDI control register |
| 174 | * @hw: pointer to the HW structure | 174 | * @hw: pointer to the HW structure |
| 175 | * @offset: register offset to write to | 175 | * @offset: register offset to write to |
| 176 | * @data: data to write to register at offset | 176 | * @data: data to write to register at offset |
| 177 | * | 177 | * |
| 178 | * Writes data to MDI control register in the PHY at offset. | 178 | * Writes data to MDI control register in the PHY at offset. |
| 179 | **/ | 179 | **/ |
| 180 | static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) | 180 | s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) |
| 181 | { | 181 | { |
| 182 | struct e1000_phy_info *phy = &hw->phy; | 182 | struct e1000_phy_info *phy = &hw->phy; |
| 183 | u32 i, mdic = 0; | 183 | u32 i, mdic = 0; |
| @@ -199,9 +199,13 @@ static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) | |||
| 199 | 199 | ||
| 200 | ew32(MDIC, mdic); | 200 | ew32(MDIC, mdic); |
| 201 | 201 | ||
| 202 | /* Poll the ready bit to see if the MDI read completed */ | 202 | /* |
| 203 | for (i = 0; i < E1000_GEN_POLL_TIMEOUT; i++) { | 203 | * Poll the ready bit to see if the MDI read completed |
| 204 | udelay(5); | 204 | * Increasing the time out as testing showed failures with |
| 205 | * the lower time out | ||
| 206 | */ | ||
| 207 | for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { | ||
| 208 | udelay(50); | ||
| 205 | mdic = er32(MDIC); | 209 | mdic = er32(MDIC); |
| 206 | if (mdic & E1000_MDIC_READY) | 210 | if (mdic & E1000_MDIC_READY) |
| 207 | break; | 211 | break; |
| @@ -210,6 +214,10 @@ static s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) | |||
| 210 | hw_dbg(hw, "MDI Write did not complete\n"); | 214 | hw_dbg(hw, "MDI Write did not complete\n"); |
| 211 | return -E1000_ERR_PHY; | 215 | return -E1000_ERR_PHY; |
| 212 | } | 216 | } |
| 217 | if (mdic & E1000_MDIC_ERROR) { | ||
| 218 | hw_dbg(hw, "MDI Error\n"); | ||
| 219 | return -E1000_ERR_PHY; | ||
| 220 | } | ||
| 213 | 221 | ||
| 214 | return 0; | 222 | return 0; |
| 215 | } | 223 | } |
| @@ -232,9 +240,8 @@ s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) | |||
| 232 | if (ret_val) | 240 | if (ret_val) |
| 233 | return ret_val; | 241 | return ret_val; |
| 234 | 242 | ||
| 235 | ret_val = e1000_read_phy_reg_mdic(hw, | 243 | ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, |
| 236 | MAX_PHY_REG_ADDRESS & offset, | 244 | data); |
| 237 | data); | ||
| 238 | 245 | ||
| 239 | hw->phy.ops.release_phy(hw); | 246 | hw->phy.ops.release_phy(hw); |
| 240 | 247 | ||
| @@ -258,9 +265,8 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) | |||
| 258 | if (ret_val) | 265 | if (ret_val) |
| 259 | return ret_val; | 266 | return ret_val; |
| 260 | 267 | ||
| 261 | ret_val = e1000_write_phy_reg_mdic(hw, | 268 | ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, |
| 262 | MAX_PHY_REG_ADDRESS & offset, | 269 | data); |
| 263 | data); | ||
| 264 | 270 | ||
| 265 | hw->phy.ops.release_phy(hw); | 271 | hw->phy.ops.release_phy(hw); |
| 266 | 272 | ||
| @@ -286,18 +292,17 @@ s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) | |||
| 286 | return ret_val; | 292 | return ret_val; |
| 287 | 293 | ||
| 288 | if (offset > MAX_PHY_MULTI_PAGE_REG) { | 294 | if (offset > MAX_PHY_MULTI_PAGE_REG) { |
| 289 | ret_val = e1000_write_phy_reg_mdic(hw, | 295 | ret_val = e1000e_write_phy_reg_mdic(hw, |
| 290 | IGP01E1000_PHY_PAGE_SELECT, | 296 | IGP01E1000_PHY_PAGE_SELECT, |
| 291 | (u16)offset); | 297 | (u16)offset); |
| 292 | if (ret_val) { | 298 | if (ret_val) { |
| 293 | hw->phy.ops.release_phy(hw); | 299 | hw->phy.ops.release_phy(hw); |
| 294 | return ret_val; | 300 | return ret_val; |
| 295 | } | 301 | } |
| 296 | } | 302 | } |
| 297 | 303 | ||
| 298 | ret_val = e1000_read_phy_reg_mdic(hw, | 304 | ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, |
| 299 | MAX_PHY_REG_ADDRESS & offset, | 305 | data); |
| 300 | data); | ||
| 301 | 306 | ||
| 302 | hw->phy.ops.release_phy(hw); | 307 | hw->phy.ops.release_phy(hw); |
| 303 | 308 | ||
| @@ -322,18 +327,17 @@ s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) | |||
| 322 | return ret_val; | 327 | return ret_val; |
| 323 | 328 | ||
| 324 | if (offset > MAX_PHY_MULTI_PAGE_REG) { | 329 | if (offset > MAX_PHY_MULTI_PAGE_REG) { |
| 325 | ret_val = e1000_write_phy_reg_mdic(hw, | 330 | ret_val = e1000e_write_phy_reg_mdic(hw, |
| 326 | IGP01E1000_PHY_PAGE_SELECT, | 331 | IGP01E1000_PHY_PAGE_SELECT, |
| 327 | (u16)offset); | 332 | (u16)offset); |
| 328 | if (ret_val) { | 333 | if (ret_val) { |
| 329 | hw->phy.ops.release_phy(hw); | 334 | hw->phy.ops.release_phy(hw); |
| 330 | return ret_val; | 335 | return ret_val; |
| 331 | } | 336 | } |
| 332 | } | 337 | } |
| 333 | 338 | ||
| 334 | ret_val = e1000_write_phy_reg_mdic(hw, | 339 | ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, |
| 335 | MAX_PHY_REG_ADDRESS & offset, | 340 | data); |
| 336 | data); | ||
| 337 | 341 | ||
| 338 | hw->phy.ops.release_phy(hw); | 342 | hw->phy.ops.release_phy(hw); |
| 339 | 343 | ||
| @@ -420,7 +424,9 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) | |||
| 420 | if (ret_val) | 424 | if (ret_val) |
| 421 | return ret_val; | 425 | return ret_val; |
| 422 | 426 | ||
| 423 | phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; | 427 | /* For newer PHYs this bit is downshift enable */ |
| 428 | if (phy->type == e1000_phy_m88) | ||
| 429 | phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; | ||
| 424 | 430 | ||
| 425 | /* | 431 | /* |
| 426 | * Options: | 432 | * Options: |
| @@ -463,7 +469,7 @@ s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) | |||
| 463 | if (ret_val) | 469 | if (ret_val) |
| 464 | return ret_val; | 470 | return ret_val; |
| 465 | 471 | ||
| 466 | if (phy->revision < 4) { | 472 | if ((phy->type == e1000_phy_m88) && (phy->revision < 4)) { |
| 467 | /* | 473 | /* |
| 468 | * Force TX_CLK in the Extended PHY Specific Control Register | 474 | * Force TX_CLK in the Extended PHY Specific Control Register |
| 469 | * to 25MHz clock. | 475 | * to 25MHz clock. |
| @@ -518,8 +524,11 @@ s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw) | |||
| 518 | return ret_val; | 524 | return ret_val; |
| 519 | } | 525 | } |
| 520 | 526 | ||
| 521 | /* Wait 15ms for MAC to configure PHY from NVM settings. */ | 527 | /* |
| 522 | msleep(15); | 528 | * Wait 100ms for MAC to configure PHY from NVM settings, to avoid |
| 529 | * timeout issues when LFS is enabled. | ||
| 530 | */ | ||
| 531 | msleep(100); | ||
| 523 | 532 | ||
| 524 | /* disable lplu d0 during driver init */ | 533 | /* disable lplu d0 during driver init */ |
| 525 | ret_val = e1000_set_d0_lplu_state(hw, 0); | 534 | ret_val = e1000_set_d0_lplu_state(hw, 0); |
| @@ -1152,9 +1161,7 @@ s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active) | |||
| 1152 | 1161 | ||
| 1153 | if (!active) { | 1162 | if (!active) { |
| 1154 | data &= ~IGP02E1000_PM_D3_LPLU; | 1163 | data &= ~IGP02E1000_PM_D3_LPLU; |
| 1155 | ret_val = e1e_wphy(hw, | 1164 | ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); |
| 1156 | IGP02E1000_PHY_POWER_MGMT, | ||
| 1157 | data); | ||
| 1158 | if (ret_val) | 1165 | if (ret_val) |
| 1159 | return ret_val; | 1166 | return ret_val; |
| 1160 | /* | 1167 | /* |
diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index 9ff7538b7595..f9bc21c74b59 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c | |||
| @@ -2611,7 +2611,7 @@ static int ehea_stop(struct net_device *dev) | |||
| 2611 | return ret; | 2611 | return ret; |
| 2612 | } | 2612 | } |
| 2613 | 2613 | ||
| 2614 | void ehea_purge_sq(struct ehea_qp *orig_qp) | 2614 | static void ehea_purge_sq(struct ehea_qp *orig_qp) |
| 2615 | { | 2615 | { |
| 2616 | struct ehea_qp qp = *orig_qp; | 2616 | struct ehea_qp qp = *orig_qp; |
| 2617 | struct ehea_qp_init_attr *init_attr = &qp.init_attr; | 2617 | struct ehea_qp_init_attr *init_attr = &qp.init_attr; |
| @@ -2625,7 +2625,7 @@ void ehea_purge_sq(struct ehea_qp *orig_qp) | |||
| 2625 | } | 2625 | } |
| 2626 | } | 2626 | } |
| 2627 | 2627 | ||
| 2628 | void ehea_flush_sq(struct ehea_port *port) | 2628 | static void ehea_flush_sq(struct ehea_port *port) |
| 2629 | { | 2629 | { |
| 2630 | int i; | 2630 | int i; |
| 2631 | 2631 | ||
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 8c4214b0ee1f..35f66d4a4595 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
| @@ -96,6 +96,7 @@ | |||
| 96 | #define DEV_HAS_PAUSEFRAME_TX_V2 0x10000 /* device supports tx pause frames version 2 */ | 96 | #define DEV_HAS_PAUSEFRAME_TX_V2 0x10000 /* device supports tx pause frames version 2 */ |
| 97 | #define DEV_HAS_PAUSEFRAME_TX_V3 0x20000 /* device supports tx pause frames version 3 */ | 97 | #define DEV_HAS_PAUSEFRAME_TX_V3 0x20000 /* device supports tx pause frames version 3 */ |
| 98 | #define DEV_NEED_TX_LIMIT 0x40000 /* device needs to limit tx */ | 98 | #define DEV_NEED_TX_LIMIT 0x40000 /* device needs to limit tx */ |
| 99 | #define DEV_HAS_GEAR_MODE 0x80000 /* device supports gear mode */ | ||
| 99 | 100 | ||
| 100 | enum { | 101 | enum { |
| 101 | NvRegIrqStatus = 0x000, | 102 | NvRegIrqStatus = 0x000, |
| @@ -174,11 +175,13 @@ enum { | |||
| 174 | NvRegReceiverStatus = 0x98, | 175 | NvRegReceiverStatus = 0x98, |
| 175 | #define NVREG_RCVSTAT_BUSY 0x01 | 176 | #define NVREG_RCVSTAT_BUSY 0x01 |
| 176 | 177 | ||
| 177 | NvRegRandomSeed = 0x9c, | 178 | NvRegSlotTime = 0x9c, |
| 178 | #define NVREG_RNDSEED_MASK 0x00ff | 179 | #define NVREG_SLOTTIME_LEGBF_ENABLED 0x80000000 |
| 179 | #define NVREG_RNDSEED_FORCE 0x7f00 | 180 | #define NVREG_SLOTTIME_10_100_FULL 0x00007f00 |
| 180 | #define NVREG_RNDSEED_FORCE2 0x2d00 | 181 | #define NVREG_SLOTTIME_1000_FULL 0x0003ff00 |
| 181 | #define NVREG_RNDSEED_FORCE3 0x7400 | 182 | #define NVREG_SLOTTIME_HALF 0x0000ff00 |
| 183 | #define NVREG_SLOTTIME_DEFAULT 0x00007f00 | ||
| 184 | #define NVREG_SLOTTIME_MASK 0x000000ff | ||
| 182 | 185 | ||
| 183 | NvRegTxDeferral = 0xA0, | 186 | NvRegTxDeferral = 0xA0, |
| 184 | #define NVREG_TX_DEFERRAL_DEFAULT 0x15050f | 187 | #define NVREG_TX_DEFERRAL_DEFAULT 0x15050f |
| @@ -201,6 +204,11 @@ enum { | |||
| 201 | 204 | ||
| 202 | NvRegPhyInterface = 0xC0, | 205 | NvRegPhyInterface = 0xC0, |
| 203 | #define PHY_RGMII 0x10000000 | 206 | #define PHY_RGMII 0x10000000 |
| 207 | NvRegBackOffControl = 0xC4, | ||
| 208 | #define NVREG_BKOFFCTRL_DEFAULT 0x70000000 | ||
| 209 | #define NVREG_BKOFFCTRL_SEED_MASK 0x000003ff | ||
| 210 | #define NVREG_BKOFFCTRL_SELECT 24 | ||
| 211 | #define NVREG_BKOFFCTRL_GEAR 12 | ||
| 204 | 212 | ||
| 205 | NvRegTxRingPhysAddr = 0x100, | 213 | NvRegTxRingPhysAddr = 0x100, |
| 206 | NvRegRxRingPhysAddr = 0x104, | 214 | NvRegRxRingPhysAddr = 0x104, |
| @@ -352,6 +360,7 @@ union ring_type { | |||
| 352 | 360 | ||
| 353 | #define NV_TX_LASTPACKET (1<<16) | 361 | #define NV_TX_LASTPACKET (1<<16) |
| 354 | #define NV_TX_RETRYERROR (1<<19) | 362 | #define NV_TX_RETRYERROR (1<<19) |
| 363 | #define NV_TX_RETRYCOUNT_MASK (0xF<<20) | ||
| 355 | #define NV_TX_FORCED_INTERRUPT (1<<24) | 364 | #define NV_TX_FORCED_INTERRUPT (1<<24) |
| 356 | #define NV_TX_DEFERRED (1<<26) | 365 | #define NV_TX_DEFERRED (1<<26) |
| 357 | #define NV_TX_CARRIERLOST (1<<27) | 366 | #define NV_TX_CARRIERLOST (1<<27) |
| @@ -362,6 +371,7 @@ union ring_type { | |||
| 362 | 371 | ||
| 363 | #define NV_TX2_LASTPACKET (1<<29) | 372 | #define NV_TX2_LASTPACKET (1<<29) |
| 364 | #define NV_TX2_RETRYERROR (1<<18) | 373 | #define NV_TX2_RETRYERROR (1<<18) |
| 374 | #define NV_TX2_RETRYCOUNT_MASK (0xF<<19) | ||
| 365 | #define NV_TX2_FORCED_INTERRUPT (1<<30) | 375 | #define NV_TX2_FORCED_INTERRUPT (1<<30) |
| 366 | #define NV_TX2_DEFERRED (1<<25) | 376 | #define NV_TX2_DEFERRED (1<<25) |
| 367 | #define NV_TX2_CARRIERLOST (1<<26) | 377 | #define NV_TX2_CARRIERLOST (1<<26) |
| @@ -473,16 +483,22 @@ union ring_type { | |||
| 473 | #define DESC_VER_3 3 | 483 | #define DESC_VER_3 3 |
| 474 | 484 | ||
| 475 | /* PHY defines */ | 485 | /* PHY defines */ |
| 476 | #define PHY_OUI_MARVELL 0x5043 | 486 | #define PHY_OUI_MARVELL 0x5043 |
| 477 | #define PHY_OUI_CICADA 0x03f1 | 487 | #define PHY_OUI_CICADA 0x03f1 |
| 478 | #define PHY_OUI_VITESSE 0x01c1 | 488 | #define PHY_OUI_VITESSE 0x01c1 |
| 479 | #define PHY_OUI_REALTEK 0x0732 | 489 | #define PHY_OUI_REALTEK 0x0732 |
| 490 | #define PHY_OUI_REALTEK2 0x0020 | ||
| 480 | #define PHYID1_OUI_MASK 0x03ff | 491 | #define PHYID1_OUI_MASK 0x03ff |
| 481 | #define PHYID1_OUI_SHFT 6 | 492 | #define PHYID1_OUI_SHFT 6 |
| 482 | #define PHYID2_OUI_MASK 0xfc00 | 493 | #define PHYID2_OUI_MASK 0xfc00 |
| 483 | #define PHYID2_OUI_SHFT 10 | 494 | #define PHYID2_OUI_SHFT 10 |
| 484 | #define PHYID2_MODEL_MASK 0x03f0 | 495 | #define PHYID2_MODEL_MASK 0x03f0 |
| 485 | #define PHY_MODEL_MARVELL_E3016 0x220 | 496 | #define PHY_MODEL_REALTEK_8211 0x0110 |
| 497 | #define PHY_REV_MASK 0x0001 | ||
| 498 | #define PHY_REV_REALTEK_8211B 0x0000 | ||
| 499 | #define PHY_REV_REALTEK_8211C 0x0001 | ||
| 500 | #define PHY_MODEL_REALTEK_8201 0x0200 | ||
| 501 | #define PHY_MODEL_MARVELL_E3016 0x0220 | ||
| 486 | #define PHY_MARVELL_E3016_INITMASK 0x0300 | 502 | #define PHY_MARVELL_E3016_INITMASK 0x0300 |
| 487 | #define PHY_CICADA_INIT1 0x0f000 | 503 | #define PHY_CICADA_INIT1 0x0f000 |
| 488 | #define PHY_CICADA_INIT2 0x0e00 | 504 | #define PHY_CICADA_INIT2 0x0e00 |
| @@ -509,10 +525,18 @@ union ring_type { | |||
| 509 | #define PHY_REALTEK_INIT_REG1 0x1f | 525 | #define PHY_REALTEK_INIT_REG1 0x1f |
| 510 | #define PHY_REALTEK_INIT_REG2 0x19 | 526 | #define PHY_REALTEK_INIT_REG2 0x19 |
| 511 | #define PHY_REALTEK_INIT_REG3 0x13 | 527 | #define PHY_REALTEK_INIT_REG3 0x13 |
| 528 | #define PHY_REALTEK_INIT_REG4 0x14 | ||
| 529 | #define PHY_REALTEK_INIT_REG5 0x18 | ||
| 530 | #define PHY_REALTEK_INIT_REG6 0x11 | ||
| 512 | #define PHY_REALTEK_INIT1 0x0000 | 531 | #define PHY_REALTEK_INIT1 0x0000 |
| 513 | #define PHY_REALTEK_INIT2 0x8e00 | 532 | #define PHY_REALTEK_INIT2 0x8e00 |
| 514 | #define PHY_REALTEK_INIT3 0x0001 | 533 | #define PHY_REALTEK_INIT3 0x0001 |
| 515 | #define PHY_REALTEK_INIT4 0xad17 | 534 | #define PHY_REALTEK_INIT4 0xad17 |
| 535 | #define PHY_REALTEK_INIT5 0xfb54 | ||
| 536 | #define PHY_REALTEK_INIT6 0xf5c7 | ||
| 537 | #define PHY_REALTEK_INIT7 0x1000 | ||
| 538 | #define PHY_REALTEK_INIT8 0x0003 | ||
| 539 | #define PHY_REALTEK_INIT_MSK1 0x0003 | ||
| 516 | 540 | ||
| 517 | #define PHY_GIGABIT 0x0100 | 541 | #define PHY_GIGABIT 0x0100 |
| 518 | 542 | ||
| @@ -691,6 +715,7 @@ struct fe_priv { | |||
| 691 | int wolenabled; | 715 | int wolenabled; |
| 692 | unsigned int phy_oui; | 716 | unsigned int phy_oui; |
| 693 | unsigned int phy_model; | 717 | unsigned int phy_model; |
| 718 | unsigned int phy_rev; | ||
| 694 | u16 gigabit; | 719 | u16 gigabit; |
| 695 | int intr_test; | 720 | int intr_test; |
| 696 | int recover_error; | 721 | int recover_error; |
| @@ -704,6 +729,7 @@ struct fe_priv { | |||
| 704 | u32 txrxctl_bits; | 729 | u32 txrxctl_bits; |
| 705 | u32 vlanctl_bits; | 730 | u32 vlanctl_bits; |
| 706 | u32 driver_data; | 731 | u32 driver_data; |
| 732 | u32 device_id; | ||
| 707 | u32 register_size; | 733 | u32 register_size; |
| 708 | int rx_csum; | 734 | int rx_csum; |
| 709 | u32 mac_in_use; | 735 | u32 mac_in_use; |
| @@ -814,6 +840,16 @@ enum { | |||
| 814 | }; | 840 | }; |
| 815 | static int dma_64bit = NV_DMA_64BIT_ENABLED; | 841 | static int dma_64bit = NV_DMA_64BIT_ENABLED; |
| 816 | 842 | ||
| 843 | /* | ||
| 844 | * Crossover Detection | ||
| 845 | * Realtek 8201 phy + some OEM boards do not work properly. | ||
| 846 | */ | ||
| 847 | enum { | ||
| 848 | NV_CROSSOVER_DETECTION_DISABLED, | ||
| 849 | NV_CROSSOVER_DETECTION_ENABLED | ||
| 850 | }; | ||
| 851 | static int phy_cross = NV_CROSSOVER_DETECTION_DISABLED; | ||
| 852 | |||
| 817 | static inline struct fe_priv *get_nvpriv(struct net_device *dev) | 853 | static inline struct fe_priv *get_nvpriv(struct net_device *dev) |
| 818 | { | 854 | { |
| 819 | return netdev_priv(dev); | 855 | return netdev_priv(dev); |
| @@ -1078,25 +1114,53 @@ static int phy_init(struct net_device *dev) | |||
| 1078 | } | 1114 | } |
| 1079 | } | 1115 | } |
| 1080 | if (np->phy_oui == PHY_OUI_REALTEK) { | 1116 | if (np->phy_oui == PHY_OUI_REALTEK) { |
| 1081 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { | 1117 | if (np->phy_model == PHY_MODEL_REALTEK_8211 && |
| 1082 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | 1118 | np->phy_rev == PHY_REV_REALTEK_8211B) { |
| 1083 | return PHY_ERROR; | 1119 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { |
| 1084 | } | 1120 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); |
| 1085 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) { | 1121 | return PHY_ERROR; |
| 1086 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | 1122 | } |
| 1087 | return PHY_ERROR; | 1123 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) { |
| 1088 | } | 1124 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); |
| 1089 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) { | 1125 | return PHY_ERROR; |
| 1090 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | 1126 | } |
| 1091 | return PHY_ERROR; | 1127 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) { |
| 1092 | } | 1128 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); |
| 1093 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) { | 1129 | return PHY_ERROR; |
| 1094 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | 1130 | } |
| 1095 | return PHY_ERROR; | 1131 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) { |
| 1132 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | ||
| 1133 | return PHY_ERROR; | ||
| 1134 | } | ||
| 1135 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5)) { | ||
| 1136 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | ||
| 1137 | return PHY_ERROR; | ||
| 1138 | } | ||
| 1139 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6)) { | ||
| 1140 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | ||
| 1141 | return PHY_ERROR; | ||
| 1142 | } | ||
| 1143 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { | ||
| 1144 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | ||
| 1145 | return PHY_ERROR; | ||
| 1146 | } | ||
| 1096 | } | 1147 | } |
| 1097 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { | 1148 | if (np->phy_model == PHY_MODEL_REALTEK_8201) { |
| 1098 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | 1149 | if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 || |
| 1099 | return PHY_ERROR; | 1150 | np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 || |
| 1151 | np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_34 || | ||
| 1152 | np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_35 || | ||
| 1153 | np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_36 || | ||
| 1154 | np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_37 || | ||
| 1155 | np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_38 || | ||
| 1156 | np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_39) { | ||
| 1157 | phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ); | ||
| 1158 | phy_reserved |= PHY_REALTEK_INIT7; | ||
| 1159 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) { | ||
| 1160 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | ||
| 1161 | return PHY_ERROR; | ||
| 1162 | } | ||
| 1163 | } | ||
| 1100 | } | 1164 | } |
| 1101 | } | 1165 | } |
| 1102 | 1166 | ||
| @@ -1236,26 +1300,71 @@ static int phy_init(struct net_device *dev) | |||
| 1236 | } | 1300 | } |
| 1237 | } | 1301 | } |
| 1238 | if (np->phy_oui == PHY_OUI_REALTEK) { | 1302 | if (np->phy_oui == PHY_OUI_REALTEK) { |
| 1239 | /* reset could have cleared these out, set them back */ | 1303 | if (np->phy_model == PHY_MODEL_REALTEK_8211 && |
| 1240 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { | 1304 | np->phy_rev == PHY_REV_REALTEK_8211B) { |
| 1241 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | 1305 | /* reset could have cleared these out, set them back */ |
| 1242 | return PHY_ERROR; | 1306 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { |
| 1243 | } | 1307 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); |
| 1244 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) { | 1308 | return PHY_ERROR; |
| 1245 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | 1309 | } |
| 1246 | return PHY_ERROR; | 1310 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, PHY_REALTEK_INIT2)) { |
| 1247 | } | 1311 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); |
| 1248 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) { | 1312 | return PHY_ERROR; |
| 1249 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | 1313 | } |
| 1250 | return PHY_ERROR; | 1314 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) { |
| 1251 | } | 1315 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); |
| 1252 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) { | 1316 | return PHY_ERROR; |
| 1253 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | 1317 | } |
| 1254 | return PHY_ERROR; | 1318 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG3, PHY_REALTEK_INIT4)) { |
| 1319 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | ||
| 1320 | return PHY_ERROR; | ||
| 1321 | } | ||
| 1322 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG4, PHY_REALTEK_INIT5)) { | ||
| 1323 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | ||
| 1324 | return PHY_ERROR; | ||
| 1325 | } | ||
| 1326 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG5, PHY_REALTEK_INIT6)) { | ||
| 1327 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | ||
| 1328 | return PHY_ERROR; | ||
| 1329 | } | ||
| 1330 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { | ||
| 1331 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | ||
| 1332 | return PHY_ERROR; | ||
| 1333 | } | ||
| 1255 | } | 1334 | } |
| 1256 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { | 1335 | if (np->phy_model == PHY_MODEL_REALTEK_8201) { |
| 1257 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | 1336 | if (np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_32 || |
| 1258 | return PHY_ERROR; | 1337 | np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_33 || |
| 1338 | np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_34 || | ||
| 1339 | np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_35 || | ||
| 1340 | np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_36 || | ||
| 1341 | np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_37 || | ||
| 1342 | np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_38 || | ||
| 1343 | np->device_id == PCI_DEVICE_ID_NVIDIA_NVENET_39) { | ||
| 1344 | phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, MII_READ); | ||
| 1345 | phy_reserved |= PHY_REALTEK_INIT7; | ||
| 1346 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG6, phy_reserved)) { | ||
| 1347 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | ||
| 1348 | return PHY_ERROR; | ||
| 1349 | } | ||
| 1350 | } | ||
| 1351 | if (phy_cross == NV_CROSSOVER_DETECTION_DISABLED) { | ||
| 1352 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3)) { | ||
| 1353 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | ||
| 1354 | return PHY_ERROR; | ||
| 1355 | } | ||
| 1356 | phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, MII_READ); | ||
| 1357 | phy_reserved &= ~PHY_REALTEK_INIT_MSK1; | ||
| 1358 | phy_reserved |= PHY_REALTEK_INIT3; | ||
| 1359 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, phy_reserved)) { | ||
| 1360 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | ||
| 1361 | return PHY_ERROR; | ||
| 1362 | } | ||
| 1363 | if (mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1)) { | ||
| 1364 | printk(KERN_INFO "%s: phy init failed.\n", pci_name(np->pci_dev)); | ||
| 1365 | return PHY_ERROR; | ||
| 1366 | } | ||
| 1367 | } | ||
| 1259 | } | 1368 | } |
| 1260 | } | 1369 | } |
| 1261 | 1370 | ||
| @@ -1769,6 +1878,115 @@ static inline u32 nv_get_empty_tx_slots(struct fe_priv *np) | |||
| 1769 | return (u32)(np->tx_ring_size - ((np->tx_ring_size + (np->put_tx_ctx - np->get_tx_ctx)) % np->tx_ring_size)); | 1878 | return (u32)(np->tx_ring_size - ((np->tx_ring_size + (np->put_tx_ctx - np->get_tx_ctx)) % np->tx_ring_size)); |
| 1770 | } | 1879 | } |
| 1771 | 1880 | ||
| 1881 | static void nv_legacybackoff_reseed(struct net_device *dev) | ||
| 1882 | { | ||
| 1883 | u8 __iomem *base = get_hwbase(dev); | ||
| 1884 | u32 reg; | ||
| 1885 | u32 low; | ||
| 1886 | int tx_status = 0; | ||
| 1887 | |||
| 1888 | reg = readl(base + NvRegSlotTime) & ~NVREG_SLOTTIME_MASK; | ||
| 1889 | get_random_bytes(&low, sizeof(low)); | ||
| 1890 | reg |= low & NVREG_SLOTTIME_MASK; | ||
| 1891 | |||
| 1892 | /* Need to stop tx before change takes effect. | ||
| 1893 | * Caller has already gained np->lock. | ||
| 1894 | */ | ||
| 1895 | tx_status = readl(base + NvRegTransmitterControl) & NVREG_XMITCTL_START; | ||
| 1896 | if (tx_status) | ||
| 1897 | nv_stop_tx(dev); | ||
| 1898 | nv_stop_rx(dev); | ||
| 1899 | writel(reg, base + NvRegSlotTime); | ||
| 1900 | if (tx_status) | ||
| 1901 | nv_start_tx(dev); | ||
| 1902 | nv_start_rx(dev); | ||
| 1903 | } | ||
| 1904 | |||
| 1905 | /* Gear Backoff Seeds */ | ||
| 1906 | #define BACKOFF_SEEDSET_ROWS 8 | ||
| 1907 | #define BACKOFF_SEEDSET_LFSRS 15 | ||
| 1908 | |||
| 1909 | /* Known Good seed sets */ | ||
| 1910 | static const u32 main_seedset[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = { | ||
| 1911 | {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874}, | ||
| 1912 | {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 385, 761, 790, 974}, | ||
| 1913 | {145, 155, 165, 175, 185, 196, 235, 245, 255, 265, 275, 285, 660, 690, 874}, | ||
| 1914 | {245, 255, 265, 575, 385, 298, 335, 345, 355, 366, 375, 386, 761, 790, 974}, | ||
| 1915 | {266, 265, 276, 585, 397, 208, 345, 355, 365, 376, 385, 396, 771, 700, 984}, | ||
| 1916 | {266, 265, 276, 586, 397, 208, 346, 355, 365, 376, 285, 396, 771, 700, 984}, | ||
| 1917 | {366, 365, 376, 686, 497, 308, 447, 455, 466, 476, 485, 496, 871, 800, 84}, | ||
| 1918 | {466, 465, 476, 786, 597, 408, 547, 555, 566, 576, 585, 597, 971, 900, 184}}; | ||
| 1919 | |||
| 1920 | static const u32 gear_seedset[BACKOFF_SEEDSET_ROWS][BACKOFF_SEEDSET_LFSRS] = { | ||
| 1921 | {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295}, | ||
| 1922 | {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}, | ||
| 1923 | {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 397}, | ||
| 1924 | {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295}, | ||
| 1925 | {251, 262, 273, 324, 319, 508, 375, 364, 341, 371, 398, 193, 375, 30, 295}, | ||
| 1926 | {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}, | ||
| 1927 | {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}, | ||
| 1928 | {351, 375, 373, 469, 551, 639, 477, 464, 441, 472, 498, 293, 476, 130, 395}}; | ||
| 1929 | |||
| 1930 | static void nv_gear_backoff_reseed(struct net_device *dev) | ||
| 1931 | { | ||
| 1932 | u8 __iomem *base = get_hwbase(dev); | ||
| 1933 | u32 miniseed1, miniseed2, miniseed2_reversed, miniseed3, miniseed3_reversed; | ||
| 1934 | u32 temp, seedset, combinedSeed; | ||
| 1935 | int i; | ||
| 1936 | |||
| 1937 | /* Setup seed for free running LFSR */ | ||
| 1938 | /* We are going to read the time stamp counter 3 times | ||
| 1939 | and swizzle bits around to increase randomness */ | ||
| 1940 | get_random_bytes(&miniseed1, sizeof(miniseed1)); | ||
| 1941 | miniseed1 &= 0x0fff; | ||
| 1942 | if (miniseed1 == 0) | ||
| 1943 | miniseed1 = 0xabc; | ||
| 1944 | |||
| 1945 | get_random_bytes(&miniseed2, sizeof(miniseed2)); | ||
| 1946 | miniseed2 &= 0x0fff; | ||
| 1947 | if (miniseed2 == 0) | ||
| 1948 | miniseed2 = 0xabc; | ||
| 1949 | miniseed2_reversed = | ||
| 1950 | ((miniseed2 & 0xF00) >> 8) | | ||
| 1951 | (miniseed2 & 0x0F0) | | ||
| 1952 | ((miniseed2 & 0x00F) << 8); | ||
| 1953 | |||
| 1954 | get_random_bytes(&miniseed3, sizeof(miniseed3)); | ||
| 1955 | miniseed3 &= 0x0fff; | ||
| 1956 | if (miniseed3 == 0) | ||
| 1957 | miniseed3 = 0xabc; | ||
| 1958 | miniseed3_reversed = | ||
| 1959 | ((miniseed3 & 0xF00) >> 8) | | ||
| 1960 | (miniseed3 & 0x0F0) | | ||
| 1961 | ((miniseed3 & 0x00F) << 8); | ||
| 1962 | |||
| 1963 | combinedSeed = ((miniseed1 ^ miniseed2_reversed) << 12) | | ||
| 1964 | (miniseed2 ^ miniseed3_reversed); | ||
| 1965 | |||
| 1966 | /* Seeds can not be zero */ | ||
| 1967 | if ((combinedSeed & NVREG_BKOFFCTRL_SEED_MASK) == 0) | ||
| 1968 | combinedSeed |= 0x08; | ||
| 1969 | if ((combinedSeed & (NVREG_BKOFFCTRL_SEED_MASK << NVREG_BKOFFCTRL_GEAR)) == 0) | ||
| 1970 | combinedSeed |= 0x8000; | ||
| 1971 | |||
| 1972 | /* No need to disable tx here */ | ||
| 1973 | temp = NVREG_BKOFFCTRL_DEFAULT | (0 << NVREG_BKOFFCTRL_SELECT); | ||
| 1974 | temp |= combinedSeed & NVREG_BKOFFCTRL_SEED_MASK; | ||
| 1975 | temp |= combinedSeed >> NVREG_BKOFFCTRL_GEAR; | ||
| 1976 | writel(temp,base + NvRegBackOffControl); | ||
| 1977 | |||
| 1978 | /* Setup seeds for all gear LFSRs. */ | ||
| 1979 | get_random_bytes(&seedset, sizeof(seedset)); | ||
| 1980 | seedset = seedset % BACKOFF_SEEDSET_ROWS; | ||
| 1981 | for (i = 1; i <= BACKOFF_SEEDSET_LFSRS; i++) | ||
| 1982 | { | ||
| 1983 | temp = NVREG_BKOFFCTRL_DEFAULT | (i << NVREG_BKOFFCTRL_SELECT); | ||
| 1984 | temp |= main_seedset[seedset][i-1] & 0x3ff; | ||
| 1985 | temp |= ((gear_seedset[seedset][i-1] & 0x3ff) << NVREG_BKOFFCTRL_GEAR); | ||
| 1986 | writel(temp, base + NvRegBackOffControl); | ||
| 1987 | } | ||
| 1988 | } | ||
| 1989 | |||
| 1772 | /* | 1990 | /* |
| 1773 | * nv_start_xmit: dev->hard_start_xmit function | 1991 | * nv_start_xmit: dev->hard_start_xmit function |
| 1774 | * Called with netif_tx_lock held. | 1992 | * Called with netif_tx_lock held. |
| @@ -2088,6 +2306,8 @@ static void nv_tx_done(struct net_device *dev) | |||
| 2088 | dev->stats.tx_fifo_errors++; | 2306 | dev->stats.tx_fifo_errors++; |
| 2089 | if (flags & NV_TX_CARRIERLOST) | 2307 | if (flags & NV_TX_CARRIERLOST) |
| 2090 | dev->stats.tx_carrier_errors++; | 2308 | dev->stats.tx_carrier_errors++; |
| 2309 | if ((flags & NV_TX_RETRYERROR) && !(flags & NV_TX_RETRYCOUNT_MASK)) | ||
| 2310 | nv_legacybackoff_reseed(dev); | ||
| 2091 | dev->stats.tx_errors++; | 2311 | dev->stats.tx_errors++; |
| 2092 | } else { | 2312 | } else { |
| 2093 | dev->stats.tx_packets++; | 2313 | dev->stats.tx_packets++; |
| @@ -2103,6 +2323,8 @@ static void nv_tx_done(struct net_device *dev) | |||
| 2103 | dev->stats.tx_fifo_errors++; | 2323 | dev->stats.tx_fifo_errors++; |
| 2104 | if (flags & NV_TX2_CARRIERLOST) | 2324 | if (flags & NV_TX2_CARRIERLOST) |
| 2105 | dev->stats.tx_carrier_errors++; | 2325 | dev->stats.tx_carrier_errors++; |
| 2326 | if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK)) | ||
| 2327 | nv_legacybackoff_reseed(dev); | ||
| 2106 | dev->stats.tx_errors++; | 2328 | dev->stats.tx_errors++; |
| 2107 | } else { | 2329 | } else { |
| 2108 | dev->stats.tx_packets++; | 2330 | dev->stats.tx_packets++; |
| @@ -2144,6 +2366,15 @@ static void nv_tx_done_optimized(struct net_device *dev, int limit) | |||
| 2144 | if (flags & NV_TX2_LASTPACKET) { | 2366 | if (flags & NV_TX2_LASTPACKET) { |
| 2145 | if (!(flags & NV_TX2_ERROR)) | 2367 | if (!(flags & NV_TX2_ERROR)) |
| 2146 | dev->stats.tx_packets++; | 2368 | dev->stats.tx_packets++; |
| 2369 | else { | ||
| 2370 | if ((flags & NV_TX2_RETRYERROR) && !(flags & NV_TX2_RETRYCOUNT_MASK)) { | ||
| 2371 | if (np->driver_data & DEV_HAS_GEAR_MODE) | ||
| 2372 | nv_gear_backoff_reseed(dev); | ||
| 2373 | else | ||
| 2374 | nv_legacybackoff_reseed(dev); | ||
| 2375 | } | ||
| 2376 | } | ||
| 2377 | |||
| 2147 | dev_kfree_skb_any(np->get_tx_ctx->skb); | 2378 | dev_kfree_skb_any(np->get_tx_ctx->skb); |
| 2148 | np->get_tx_ctx->skb = NULL; | 2379 | np->get_tx_ctx->skb = NULL; |
| 2149 | 2380 | ||
| @@ -2905,15 +3136,14 @@ set_speed: | |||
| 2905 | } | 3136 | } |
| 2906 | 3137 | ||
| 2907 | if (np->gigabit == PHY_GIGABIT) { | 3138 | if (np->gigabit == PHY_GIGABIT) { |
| 2908 | phyreg = readl(base + NvRegRandomSeed); | 3139 | phyreg = readl(base + NvRegSlotTime); |
| 2909 | phyreg &= ~(0x3FF00); | 3140 | phyreg &= ~(0x3FF00); |
| 2910 | if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10) | 3141 | if (((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_10) || |
| 2911 | phyreg |= NVREG_RNDSEED_FORCE3; | 3142 | ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100)) |
| 2912 | else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_100) | 3143 | phyreg |= NVREG_SLOTTIME_10_100_FULL; |
| 2913 | phyreg |= NVREG_RNDSEED_FORCE2; | ||
| 2914 | else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000) | 3144 | else if ((np->linkspeed & 0xFFF) == NVREG_LINKSPEED_1000) |
| 2915 | phyreg |= NVREG_RNDSEED_FORCE; | 3145 | phyreg |= NVREG_SLOTTIME_1000_FULL; |
| 2916 | writel(phyreg, base + NvRegRandomSeed); | 3146 | writel(phyreg, base + NvRegSlotTime); |
| 2917 | } | 3147 | } |
| 2918 | 3148 | ||
| 2919 | phyreg = readl(base + NvRegPhyInterface); | 3149 | phyreg = readl(base + NvRegPhyInterface); |
| @@ -4843,6 +5073,7 @@ static int nv_open(struct net_device *dev) | |||
| 4843 | u8 __iomem *base = get_hwbase(dev); | 5073 | u8 __iomem *base = get_hwbase(dev); |
| 4844 | int ret = 1; | 5074 | int ret = 1; |
| 4845 | int oom, i; | 5075 | int oom, i; |
| 5076 | u32 low; | ||
| 4846 | 5077 | ||
| 4847 | dprintk(KERN_DEBUG "nv_open: begin\n"); | 5078 | dprintk(KERN_DEBUG "nv_open: begin\n"); |
| 4848 | 5079 | ||
| @@ -4902,8 +5133,20 @@ static int nv_open(struct net_device *dev) | |||
| 4902 | writel(np->rx_buf_sz, base + NvRegOffloadConfig); | 5133 | writel(np->rx_buf_sz, base + NvRegOffloadConfig); |
| 4903 | 5134 | ||
| 4904 | writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus); | 5135 | writel(readl(base + NvRegReceiverStatus), base + NvRegReceiverStatus); |
| 4905 | get_random_bytes(&i, sizeof(i)); | 5136 | |
| 4906 | writel(NVREG_RNDSEED_FORCE | (i&NVREG_RNDSEED_MASK), base + NvRegRandomSeed); | 5137 | get_random_bytes(&low, sizeof(low)); |
| 5138 | low &= NVREG_SLOTTIME_MASK; | ||
| 5139 | if (np->desc_ver == DESC_VER_1) { | ||
| 5140 | writel(low|NVREG_SLOTTIME_DEFAULT, base + NvRegSlotTime); | ||
| 5141 | } else { | ||
| 5142 | if (!(np->driver_data & DEV_HAS_GEAR_MODE)) { | ||
| 5143 | /* setup legacy backoff */ | ||
| 5144 | writel(NVREG_SLOTTIME_LEGBF_ENABLED|NVREG_SLOTTIME_10_100_FULL|low, base + NvRegSlotTime); | ||
| 5145 | } else { | ||
| 5146 | writel(NVREG_SLOTTIME_10_100_FULL, base + NvRegSlotTime); | ||
| 5147 | nv_gear_backoff_reseed(dev); | ||
| 5148 | } | ||
| 5149 | } | ||
| 4907 | writel(NVREG_TX_DEFERRAL_DEFAULT, base + NvRegTxDeferral); | 5150 | writel(NVREG_TX_DEFERRAL_DEFAULT, base + NvRegTxDeferral); |
| 4908 | writel(NVREG_RX_DEFERRAL_DEFAULT, base + NvRegRxDeferral); | 5151 | writel(NVREG_RX_DEFERRAL_DEFAULT, base + NvRegRxDeferral); |
| 4909 | if (poll_interval == -1) { | 5152 | if (poll_interval == -1) { |
| @@ -5110,6 +5353,8 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
| 5110 | 5353 | ||
| 5111 | /* copy of driver data */ | 5354 | /* copy of driver data */ |
| 5112 | np->driver_data = id->driver_data; | 5355 | np->driver_data = id->driver_data; |
| 5356 | /* copy of device id */ | ||
| 5357 | np->device_id = id->device; | ||
| 5113 | 5358 | ||
| 5114 | /* handle different descriptor versions */ | 5359 | /* handle different descriptor versions */ |
| 5115 | if (id->driver_data & DEV_HAS_HIGH_DMA) { | 5360 | if (id->driver_data & DEV_HAS_HIGH_DMA) { |
| @@ -5399,6 +5644,14 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i | |||
| 5399 | pci_name(pci_dev), id1, id2, phyaddr); | 5644 | pci_name(pci_dev), id1, id2, phyaddr); |
| 5400 | np->phyaddr = phyaddr; | 5645 | np->phyaddr = phyaddr; |
| 5401 | np->phy_oui = id1 | id2; | 5646 | np->phy_oui = id1 | id2; |
| 5647 | |||
| 5648 | /* Realtek hardcoded phy id1 to all zero's on certain phys */ | ||
| 5649 | if (np->phy_oui == PHY_OUI_REALTEK2) | ||
| 5650 | np->phy_oui = PHY_OUI_REALTEK; | ||
| 5651 | /* Setup phy revision for Realtek */ | ||
| 5652 | if (np->phy_oui == PHY_OUI_REALTEK && np->phy_model == PHY_MODEL_REALTEK_8211) | ||
| 5653 | np->phy_rev = mii_rw(dev, phyaddr, MII_RESV1, MII_READ) & PHY_REV_MASK; | ||
| 5654 | |||
| 5402 | break; | 5655 | break; |
| 5403 | } | 5656 | } |
| 5404 | if (i == 33) { | 5657 | if (i == 33) { |
| @@ -5477,6 +5730,28 @@ out: | |||
| 5477 | return err; | 5730 | return err; |
| 5478 | } | 5731 | } |
| 5479 | 5732 | ||
| 5733 | static void nv_restore_phy(struct net_device *dev) | ||
| 5734 | { | ||
| 5735 | struct fe_priv *np = netdev_priv(dev); | ||
| 5736 | u16 phy_reserved, mii_control; | ||
| 5737 | |||
| 5738 | if (np->phy_oui == PHY_OUI_REALTEK && | ||
| 5739 | np->phy_model == PHY_MODEL_REALTEK_8201 && | ||
| 5740 | phy_cross == NV_CROSSOVER_DETECTION_DISABLED) { | ||
| 5741 | mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT3); | ||
| 5742 | phy_reserved = mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, MII_READ); | ||
| 5743 | phy_reserved &= ~PHY_REALTEK_INIT_MSK1; | ||
| 5744 | phy_reserved |= PHY_REALTEK_INIT8; | ||
| 5745 | mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG2, phy_reserved); | ||
| 5746 | mii_rw(dev, np->phyaddr, PHY_REALTEK_INIT_REG1, PHY_REALTEK_INIT1); | ||
| 5747 | |||
| 5748 | /* restart auto negotiation */ | ||
| 5749 | mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); | ||
| 5750 | mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE); | ||
| 5751 | mii_rw(dev, np->phyaddr, MII_BMCR, mii_control); | ||
| 5752 | } | ||
| 5753 | } | ||
| 5754 | |||
| 5480 | static void __devexit nv_remove(struct pci_dev *pci_dev) | 5755 | static void __devexit nv_remove(struct pci_dev *pci_dev) |
| 5481 | { | 5756 | { |
| 5482 | struct net_device *dev = pci_get_drvdata(pci_dev); | 5757 | struct net_device *dev = pci_get_drvdata(pci_dev); |
| @@ -5493,6 +5768,9 @@ static void __devexit nv_remove(struct pci_dev *pci_dev) | |||
| 5493 | writel(readl(base + NvRegTransmitPoll) & ~NVREG_TRANSMITPOLL_MAC_ADDR_REV, | 5768 | writel(readl(base + NvRegTransmitPoll) & ~NVREG_TRANSMITPOLL_MAC_ADDR_REV, |
| 5494 | base + NvRegTransmitPoll); | 5769 | base + NvRegTransmitPoll); |
| 5495 | 5770 | ||
| 5771 | /* restore any phy related changes */ | ||
| 5772 | nv_restore_phy(dev); | ||
| 5773 | |||
| 5496 | /* free all structures */ | 5774 | /* free all structures */ |
| 5497 | free_rings(dev); | 5775 | free_rings(dev); |
| 5498 | iounmap(get_hwbase(dev)); | 5776 | iounmap(get_hwbase(dev)); |
| @@ -5632,83 +5910,83 @@ static struct pci_device_id pci_tbl[] = { | |||
| 5632 | }, | 5910 | }, |
| 5633 | { /* MCP65 Ethernet Controller */ | 5911 | { /* MCP65 Ethernet Controller */ |
| 5634 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20), | 5912 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_20), |
| 5635 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT, | 5913 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, |
| 5636 | }, | 5914 | }, |
| 5637 | { /* MCP65 Ethernet Controller */ | 5915 | { /* MCP65 Ethernet Controller */ |
| 5638 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21), | 5916 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_21), |
| 5639 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT, | 5917 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, |
| 5640 | }, | 5918 | }, |
| 5641 | { /* MCP65 Ethernet Controller */ | 5919 | { /* MCP65 Ethernet Controller */ |
| 5642 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22), | 5920 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_22), |
| 5643 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT, | 5921 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, |
| 5644 | }, | 5922 | }, |
| 5645 | { /* MCP65 Ethernet Controller */ | 5923 | { /* MCP65 Ethernet Controller */ |
| 5646 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23), | 5924 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_23), |
| 5647 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT, | 5925 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_LARGEDESC|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, |
| 5648 | }, | 5926 | }, |
| 5649 | { /* MCP67 Ethernet Controller */ | 5927 | { /* MCP67 Ethernet Controller */ |
| 5650 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24), | 5928 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_24), |
| 5651 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, | 5929 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, |
| 5652 | }, | 5930 | }, |
| 5653 | { /* MCP67 Ethernet Controller */ | 5931 | { /* MCP67 Ethernet Controller */ |
| 5654 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25), | 5932 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_25), |
| 5655 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, | 5933 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, |
| 5656 | }, | 5934 | }, |
| 5657 | { /* MCP67 Ethernet Controller */ | 5935 | { /* MCP67 Ethernet Controller */ |
| 5658 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26), | 5936 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_26), |
| 5659 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, | 5937 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, |
| 5660 | }, | 5938 | }, |
| 5661 | { /* MCP67 Ethernet Controller */ | 5939 | { /* MCP67 Ethernet Controller */ |
| 5662 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27), | 5940 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_27), |
| 5663 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR, | 5941 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_GEAR_MODE, |
| 5664 | }, | 5942 | }, |
| 5665 | { /* MCP73 Ethernet Controller */ | 5943 | { /* MCP73 Ethernet Controller */ |
| 5666 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28), | 5944 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_28), |
| 5667 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, | 5945 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, |
| 5668 | }, | 5946 | }, |
| 5669 | { /* MCP73 Ethernet Controller */ | 5947 | { /* MCP73 Ethernet Controller */ |
| 5670 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29), | 5948 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_29), |
| 5671 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, | 5949 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, |
| 5672 | }, | 5950 | }, |
| 5673 | { /* MCP73 Ethernet Controller */ | 5951 | { /* MCP73 Ethernet Controller */ |
| 5674 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30), | 5952 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_30), |
| 5675 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, | 5953 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, |
| 5676 | }, | 5954 | }, |
| 5677 | { /* MCP73 Ethernet Controller */ | 5955 | { /* MCP73 Ethernet Controller */ |
| 5678 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31), | 5956 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_31), |
| 5679 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX, | 5957 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_HIGH_DMA|DEV_HAS_POWER_CNTRL|DEV_HAS_MSI|DEV_HAS_PAUSEFRAME_TX_V1|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_HAS_GEAR_MODE, |
| 5680 | }, | 5958 | }, |
| 5681 | { /* MCP77 Ethernet Controller */ | 5959 | { /* MCP77 Ethernet Controller */ |
| 5682 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32), | 5960 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_32), |
| 5683 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT, | 5961 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, |
| 5684 | }, | 5962 | }, |
| 5685 | { /* MCP77 Ethernet Controller */ | 5963 | { /* MCP77 Ethernet Controller */ |
| 5686 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33), | 5964 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_33), |
| 5687 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT, | 5965 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, |
| 5688 | }, | 5966 | }, |
| 5689 | { /* MCP77 Ethernet Controller */ | 5967 | { /* MCP77 Ethernet Controller */ |
| 5690 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34), | 5968 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_34), |
| 5691 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT, | 5969 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, |
| 5692 | }, | 5970 | }, |
| 5693 | { /* MCP77 Ethernet Controller */ | 5971 | { /* MCP77 Ethernet Controller */ |
| 5694 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35), | 5972 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_35), |
| 5695 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT, | 5973 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V2|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, |
| 5696 | }, | 5974 | }, |
| 5697 | { /* MCP79 Ethernet Controller */ | 5975 | { /* MCP79 Ethernet Controller */ |
| 5698 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36), | 5976 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_36), |
| 5699 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT, | 5977 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, |
| 5700 | }, | 5978 | }, |
| 5701 | { /* MCP79 Ethernet Controller */ | 5979 | { /* MCP79 Ethernet Controller */ |
| 5702 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37), | 5980 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_37), |
| 5703 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT, | 5981 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, |
| 5704 | }, | 5982 | }, |
| 5705 | { /* MCP79 Ethernet Controller */ | 5983 | { /* MCP79 Ethernet Controller */ |
| 5706 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38), | 5984 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_38), |
| 5707 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT, | 5985 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, |
| 5708 | }, | 5986 | }, |
| 5709 | { /* MCP79 Ethernet Controller */ | 5987 | { /* MCP79 Ethernet Controller */ |
| 5710 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39), | 5988 | PCI_DEVICE(PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NVENET_39), |
| 5711 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT, | 5989 | .driver_data = DEV_NEED_TIMERIRQ|DEV_NEED_LINKTIMER|DEV_HAS_CHECKSUM|DEV_HAS_HIGH_DMA|DEV_HAS_MSI|DEV_HAS_POWER_CNTRL|DEV_HAS_PAUSEFRAME_TX_V3|DEV_HAS_STATISTICS_V2|DEV_HAS_TEST_EXTENDED|DEV_HAS_MGMT_UNIT|DEV_HAS_CORRECT_MACADDR|DEV_HAS_COLLISION_FIX|DEV_NEED_TX_LIMIT|DEV_HAS_GEAR_MODE, |
| 5712 | }, | 5990 | }, |
| 5713 | {0,}, | 5991 | {0,}, |
| 5714 | }; | 5992 | }; |
| @@ -5744,6 +6022,8 @@ module_param(msix, int, 0); | |||
| 5744 | MODULE_PARM_DESC(msix, "MSIX interrupts are enabled by setting to 1 and disabled by setting to 0."); | 6022 | MODULE_PARM_DESC(msix, "MSIX interrupts are enabled by setting to 1 and disabled by setting to 0."); |
| 5745 | module_param(dma_64bit, int, 0); | 6023 | module_param(dma_64bit, int, 0); |
| 5746 | MODULE_PARM_DESC(dma_64bit, "High DMA is enabled by setting to 1 and disabled by setting to 0."); | 6024 | MODULE_PARM_DESC(dma_64bit, "High DMA is enabled by setting to 1 and disabled by setting to 0."); |
| 6025 | module_param(phy_cross, int, 0); | ||
| 6026 | MODULE_PARM_DESC(phy_cross, "Phy crossover detection for Realtek 8201 phy is enabled by setting to 1 and disabled by setting to 0."); | ||
| 5747 | 6027 | ||
| 5748 | MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>"); | 6028 | MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>"); |
| 5749 | MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver"); | 6029 | MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver"); |
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index c8c3df737d73..99a4b990939f 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
| @@ -98,7 +98,6 @@ | |||
| 98 | #include "gianfar_mii.h" | 98 | #include "gianfar_mii.h" |
| 99 | 99 | ||
| 100 | #define TX_TIMEOUT (1*HZ) | 100 | #define TX_TIMEOUT (1*HZ) |
| 101 | #define SKB_ALLOC_TIMEOUT 1000000 | ||
| 102 | #undef BRIEF_GFAR_ERRORS | 101 | #undef BRIEF_GFAR_ERRORS |
| 103 | #undef VERBOSE_GFAR_ERRORS | 102 | #undef VERBOSE_GFAR_ERRORS |
| 104 | 103 | ||
| @@ -115,7 +114,9 @@ static int gfar_enet_open(struct net_device *dev); | |||
| 115 | static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev); | 114 | static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev); |
| 116 | static void gfar_timeout(struct net_device *dev); | 115 | static void gfar_timeout(struct net_device *dev); |
| 117 | static int gfar_close(struct net_device *dev); | 116 | static int gfar_close(struct net_device *dev); |
| 118 | struct sk_buff *gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp); | 117 | struct sk_buff *gfar_new_skb(struct net_device *dev); |
| 118 | static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp, | ||
| 119 | struct sk_buff *skb); | ||
| 119 | static int gfar_set_mac_address(struct net_device *dev); | 120 | static int gfar_set_mac_address(struct net_device *dev); |
| 120 | static int gfar_change_mtu(struct net_device *dev, int new_mtu); | 121 | static int gfar_change_mtu(struct net_device *dev, int new_mtu); |
| 121 | static irqreturn_t gfar_error(int irq, void *dev_id); | 122 | static irqreturn_t gfar_error(int irq, void *dev_id); |
| @@ -783,14 +784,21 @@ int startup_gfar(struct net_device *dev) | |||
| 783 | 784 | ||
| 784 | rxbdp = priv->rx_bd_base; | 785 | rxbdp = priv->rx_bd_base; |
| 785 | for (i = 0; i < priv->rx_ring_size; i++) { | 786 | for (i = 0; i < priv->rx_ring_size; i++) { |
| 786 | struct sk_buff *skb = NULL; | 787 | struct sk_buff *skb; |
| 787 | 788 | ||
| 788 | rxbdp->status = 0; | 789 | skb = gfar_new_skb(dev); |
| 789 | 790 | ||
| 790 | skb = gfar_new_skb(dev, rxbdp); | 791 | if (!skb) { |
| 792 | printk(KERN_ERR "%s: Can't allocate RX buffers\n", | ||
| 793 | dev->name); | ||
| 794 | |||
| 795 | goto err_rxalloc_fail; | ||
| 796 | } | ||
| 791 | 797 | ||
| 792 | priv->rx_skbuff[i] = skb; | 798 | priv->rx_skbuff[i] = skb; |
| 793 | 799 | ||
| 800 | gfar_new_rxbdp(dev, rxbdp, skb); | ||
| 801 | |||
| 794 | rxbdp++; | 802 | rxbdp++; |
| 795 | } | 803 | } |
| 796 | 804 | ||
| @@ -916,6 +924,7 @@ rx_irq_fail: | |||
| 916 | tx_irq_fail: | 924 | tx_irq_fail: |
| 917 | free_irq(priv->interruptError, dev); | 925 | free_irq(priv->interruptError, dev); |
| 918 | err_irq_fail: | 926 | err_irq_fail: |
| 927 | err_rxalloc_fail: | ||
| 919 | rx_skb_fail: | 928 | rx_skb_fail: |
| 920 | free_skb_resources(priv); | 929 | free_skb_resources(priv); |
| 921 | tx_skb_fail: | 930 | tx_skb_fail: |
| @@ -1328,18 +1337,37 @@ static irqreturn_t gfar_transmit(int irq, void *dev_id) | |||
| 1328 | return IRQ_HANDLED; | 1337 | return IRQ_HANDLED; |
| 1329 | } | 1338 | } |
| 1330 | 1339 | ||
| 1331 | struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp) | 1340 | static void gfar_new_rxbdp(struct net_device *dev, struct rxbd8 *bdp, |
| 1341 | struct sk_buff *skb) | ||
| 1342 | { | ||
| 1343 | struct gfar_private *priv = netdev_priv(dev); | ||
| 1344 | u32 * status_len = (u32 *)bdp; | ||
| 1345 | u16 flags; | ||
| 1346 | |||
| 1347 | bdp->bufPtr = dma_map_single(&dev->dev, skb->data, | ||
| 1348 | priv->rx_buffer_size, DMA_FROM_DEVICE); | ||
| 1349 | |||
| 1350 | flags = RXBD_EMPTY | RXBD_INTERRUPT; | ||
| 1351 | |||
| 1352 | if (bdp == priv->rx_bd_base + priv->rx_ring_size - 1) | ||
| 1353 | flags |= RXBD_WRAP; | ||
| 1354 | |||
| 1355 | eieio(); | ||
| 1356 | |||
| 1357 | *status_len = (u32)flags << 16; | ||
| 1358 | } | ||
| 1359 | |||
| 1360 | |||
| 1361 | struct sk_buff * gfar_new_skb(struct net_device *dev) | ||
| 1332 | { | 1362 | { |
| 1333 | unsigned int alignamount; | 1363 | unsigned int alignamount; |
| 1334 | struct gfar_private *priv = netdev_priv(dev); | 1364 | struct gfar_private *priv = netdev_priv(dev); |
| 1335 | struct sk_buff *skb = NULL; | 1365 | struct sk_buff *skb = NULL; |
| 1336 | unsigned int timeout = SKB_ALLOC_TIMEOUT; | ||
| 1337 | 1366 | ||
| 1338 | /* We have to allocate the skb, so keep trying till we succeed */ | 1367 | /* We have to allocate the skb, so keep trying till we succeed */ |
| 1339 | while ((!skb) && timeout--) | 1368 | skb = netdev_alloc_skb(dev, priv->rx_buffer_size + RXBUF_ALIGNMENT); |
| 1340 | skb = dev_alloc_skb(priv->rx_buffer_size + RXBUF_ALIGNMENT); | ||
| 1341 | 1369 | ||
| 1342 | if (NULL == skb) | 1370 | if (!skb) |
| 1343 | return NULL; | 1371 | return NULL; |
| 1344 | 1372 | ||
| 1345 | alignamount = RXBUF_ALIGNMENT - | 1373 | alignamount = RXBUF_ALIGNMENT - |
| @@ -1350,15 +1378,6 @@ struct sk_buff * gfar_new_skb(struct net_device *dev, struct rxbd8 *bdp) | |||
| 1350 | */ | 1378 | */ |
| 1351 | skb_reserve(skb, alignamount); | 1379 | skb_reserve(skb, alignamount); |
| 1352 | 1380 | ||
| 1353 | bdp->bufPtr = dma_map_single(&dev->dev, skb->data, | ||
| 1354 | priv->rx_buffer_size, DMA_FROM_DEVICE); | ||
| 1355 | |||
| 1356 | bdp->length = 0; | ||
| 1357 | |||
| 1358 | /* Mark the buffer empty */ | ||
| 1359 | eieio(); | ||
| 1360 | bdp->status |= (RXBD_EMPTY | RXBD_INTERRUPT); | ||
| 1361 | |||
| 1362 | return skb; | 1381 | return skb; |
| 1363 | } | 1382 | } |
| 1364 | 1383 | ||
| @@ -1544,10 +1563,31 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) | |||
| 1544 | bdp = priv->cur_rx; | 1563 | bdp = priv->cur_rx; |
| 1545 | 1564 | ||
| 1546 | while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) { | 1565 | while (!((bdp->status & RXBD_EMPTY) || (--rx_work_limit < 0))) { |
| 1566 | struct sk_buff *newskb; | ||
| 1547 | rmb(); | 1567 | rmb(); |
| 1568 | |||
| 1569 | /* Add another skb for the future */ | ||
| 1570 | newskb = gfar_new_skb(dev); | ||
| 1571 | |||
| 1548 | skb = priv->rx_skbuff[priv->skb_currx]; | 1572 | skb = priv->rx_skbuff[priv->skb_currx]; |
| 1549 | 1573 | ||
| 1550 | if ((bdp->status & RXBD_LAST) && !(bdp->status & RXBD_ERR)) { | 1574 | /* We drop the frame if we failed to allocate a new buffer */ |
| 1575 | if (unlikely(!newskb || !(bdp->status & RXBD_LAST) || | ||
| 1576 | bdp->status & RXBD_ERR)) { | ||
| 1577 | count_errors(bdp->status, dev); | ||
| 1578 | |||
| 1579 | if (unlikely(!newskb)) | ||
| 1580 | newskb = skb; | ||
| 1581 | |||
| 1582 | if (skb) { | ||
| 1583 | dma_unmap_single(&priv->dev->dev, | ||
| 1584 | bdp->bufPtr, | ||
| 1585 | priv->rx_buffer_size, | ||
| 1586 | DMA_FROM_DEVICE); | ||
| 1587 | |||
| 1588 | dev_kfree_skb_any(skb); | ||
| 1589 | } | ||
| 1590 | } else { | ||
| 1551 | /* Increment the number of packets */ | 1591 | /* Increment the number of packets */ |
| 1552 | dev->stats.rx_packets++; | 1592 | dev->stats.rx_packets++; |
| 1553 | howmany++; | 1593 | howmany++; |
| @@ -1558,23 +1598,14 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) | |||
| 1558 | gfar_process_frame(dev, skb, pkt_len); | 1598 | gfar_process_frame(dev, skb, pkt_len); |
| 1559 | 1599 | ||
| 1560 | dev->stats.rx_bytes += pkt_len; | 1600 | dev->stats.rx_bytes += pkt_len; |
| 1561 | } else { | ||
| 1562 | count_errors(bdp->status, dev); | ||
| 1563 | |||
| 1564 | if (skb) | ||
| 1565 | dev_kfree_skb_any(skb); | ||
| 1566 | |||
| 1567 | priv->rx_skbuff[priv->skb_currx] = NULL; | ||
| 1568 | } | 1601 | } |
| 1569 | 1602 | ||
| 1570 | dev->last_rx = jiffies; | 1603 | dev->last_rx = jiffies; |
| 1571 | 1604 | ||
| 1572 | /* Clear the status flags for this buffer */ | 1605 | priv->rx_skbuff[priv->skb_currx] = newskb; |
| 1573 | bdp->status &= ~RXBD_STATS; | ||
| 1574 | 1606 | ||
| 1575 | /* Add another skb for the future */ | 1607 | /* Setup the new bdp */ |
| 1576 | skb = gfar_new_skb(dev, bdp); | 1608 | gfar_new_rxbdp(dev, bdp, newskb); |
| 1577 | priv->rx_skbuff[priv->skb_currx] = skb; | ||
| 1578 | 1609 | ||
| 1579 | /* Update to the next pointer */ | 1610 | /* Update to the next pointer */ |
| 1580 | if (bdp->status & RXBD_WRAP) | 1611 | if (bdp->status & RXBD_WRAP) |
| @@ -1584,9 +1615,8 @@ int gfar_clean_rx_ring(struct net_device *dev, int rx_work_limit) | |||
| 1584 | 1615 | ||
| 1585 | /* update to point at the next skb */ | 1616 | /* update to point at the next skb */ |
| 1586 | priv->skb_currx = | 1617 | priv->skb_currx = |
| 1587 | (priv->skb_currx + | 1618 | (priv->skb_currx + 1) & |
| 1588 | 1) & RX_RING_MOD_MASK(priv->rx_ring_size); | 1619 | RX_RING_MOD_MASK(priv->rx_ring_size); |
| 1589 | |||
| 1590 | } | 1620 | } |
| 1591 | 1621 | ||
| 1592 | /* Update the current rxbd pointer to be the next one */ | 1622 | /* Update the current rxbd pointer to be the next one */ |
| @@ -2001,12 +2031,16 @@ static irqreturn_t gfar_error(int irq, void *dev_id) | |||
| 2001 | return IRQ_HANDLED; | 2031 | return IRQ_HANDLED; |
| 2002 | } | 2032 | } |
| 2003 | 2033 | ||
| 2034 | /* work with hotplug and coldplug */ | ||
| 2035 | MODULE_ALIAS("platform:fsl-gianfar"); | ||
| 2036 | |||
| 2004 | /* Structure for a device driver */ | 2037 | /* Structure for a device driver */ |
| 2005 | static struct platform_driver gfar_driver = { | 2038 | static struct platform_driver gfar_driver = { |
| 2006 | .probe = gfar_probe, | 2039 | .probe = gfar_probe, |
| 2007 | .remove = gfar_remove, | 2040 | .remove = gfar_remove, |
| 2008 | .driver = { | 2041 | .driver = { |
| 2009 | .name = "fsl-gianfar", | 2042 | .name = "fsl-gianfar", |
| 2043 | .owner = THIS_MODULE, | ||
| 2010 | }, | 2044 | }, |
| 2011 | }; | 2045 | }; |
| 2012 | 2046 | ||
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 378a23963495..5d2108c5ac7c 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c | |||
| @@ -43,6 +43,8 @@ | |||
| 43 | #include <asm/io.h> | 43 | #include <asm/io.h> |
| 44 | #include <asm/dma.h> | 44 | #include <asm/dma.h> |
| 45 | #include <asm/uaccess.h> | 45 | #include <asm/uaccess.h> |
| 46 | #include <asm/dcr.h> | ||
| 47 | #include <asm/dcr-regs.h> | ||
| 46 | 48 | ||
| 47 | #include "core.h" | 49 | #include "core.h" |
| 48 | 50 | ||
| @@ -127,10 +129,35 @@ static struct device_node *emac_boot_list[EMAC_BOOT_LIST_SIZE]; | |||
| 127 | static inline void emac_report_timeout_error(struct emac_instance *dev, | 129 | static inline void emac_report_timeout_error(struct emac_instance *dev, |
| 128 | const char *error) | 130 | const char *error) |
| 129 | { | 131 | { |
| 130 | if (net_ratelimit()) | 132 | if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX | |
| 133 | EMAC_FTR_440EP_PHY_CLK_FIX)) | ||
| 134 | DBG(dev, "%s" NL, error); | ||
| 135 | else if (net_ratelimit()) | ||
| 131 | printk(KERN_ERR "%s: %s\n", dev->ndev->name, error); | 136 | printk(KERN_ERR "%s: %s\n", dev->ndev->name, error); |
| 132 | } | 137 | } |
| 133 | 138 | ||
| 139 | /* EMAC PHY clock workaround: | ||
| 140 | * 440EP/440GR has more sane SDR0_MFR register implementation than 440GX, | ||
| 141 | * which allows controlling each EMAC clock | ||
| 142 | */ | ||
| 143 | static inline void emac_rx_clk_tx(struct emac_instance *dev) | ||
| 144 | { | ||
| 145 | #ifdef CONFIG_PPC_DCR_NATIVE | ||
| 146 | if (emac_has_feature(dev, EMAC_FTR_440EP_PHY_CLK_FIX)) | ||
| 147 | dcri_clrset(SDR0, SDR0_MFR, | ||
| 148 | 0, SDR0_MFR_ECS >> dev->cell_index); | ||
| 149 | #endif | ||
| 150 | } | ||
| 151 | |||
| 152 | static inline void emac_rx_clk_default(struct emac_instance *dev) | ||
| 153 | { | ||
| 154 | #ifdef CONFIG_PPC_DCR_NATIVE | ||
| 155 | if (emac_has_feature(dev, EMAC_FTR_440EP_PHY_CLK_FIX)) | ||
| 156 | dcri_clrset(SDR0, SDR0_MFR, | ||
| 157 | SDR0_MFR_ECS >> dev->cell_index, 0); | ||
| 158 | #endif | ||
| 159 | } | ||
| 160 | |||
| 134 | /* PHY polling intervals */ | 161 | /* PHY polling intervals */ |
| 135 | #define PHY_POLL_LINK_ON HZ | 162 | #define PHY_POLL_LINK_ON HZ |
| 136 | #define PHY_POLL_LINK_OFF (HZ / 5) | 163 | #define PHY_POLL_LINK_OFF (HZ / 5) |
| @@ -524,7 +551,10 @@ static int emac_configure(struct emac_instance *dev) | |||
| 524 | rx_size = dev->rx_fifo_size_gige; | 551 | rx_size = dev->rx_fifo_size_gige; |
| 525 | 552 | ||
| 526 | if (dev->ndev->mtu > ETH_DATA_LEN) { | 553 | if (dev->ndev->mtu > ETH_DATA_LEN) { |
| 527 | mr1 |= EMAC_MR1_JPSM; | 554 | if (emac_has_feature(dev, EMAC_FTR_EMAC4)) |
| 555 | mr1 |= EMAC4_MR1_JPSM; | ||
| 556 | else | ||
| 557 | mr1 |= EMAC_MR1_JPSM; | ||
| 528 | dev->stop_timeout = STOP_TIMEOUT_1000_JUMBO; | 558 | dev->stop_timeout = STOP_TIMEOUT_1000_JUMBO; |
| 529 | } else | 559 | } else |
| 530 | dev->stop_timeout = STOP_TIMEOUT_1000; | 560 | dev->stop_timeout = STOP_TIMEOUT_1000; |
| @@ -708,7 +738,7 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg) | |||
| 708 | rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port); | 738 | rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port); |
| 709 | 739 | ||
| 710 | /* Wait for management interface to become idle */ | 740 | /* Wait for management interface to become idle */ |
| 711 | n = 10; | 741 | n = 20; |
| 712 | while (!emac_phy_done(dev, in_be32(&p->stacr))) { | 742 | while (!emac_phy_done(dev, in_be32(&p->stacr))) { |
| 713 | udelay(1); | 743 | udelay(1); |
| 714 | if (!--n) { | 744 | if (!--n) { |
| @@ -733,7 +763,7 @@ static int __emac_mdio_read(struct emac_instance *dev, u8 id, u8 reg) | |||
| 733 | out_be32(&p->stacr, r); | 763 | out_be32(&p->stacr, r); |
| 734 | 764 | ||
| 735 | /* Wait for read to complete */ | 765 | /* Wait for read to complete */ |
| 736 | n = 100; | 766 | n = 200; |
| 737 | while (!emac_phy_done(dev, (r = in_be32(&p->stacr)))) { | 767 | while (!emac_phy_done(dev, (r = in_be32(&p->stacr)))) { |
| 738 | udelay(1); | 768 | udelay(1); |
| 739 | if (!--n) { | 769 | if (!--n) { |
| @@ -780,7 +810,7 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg, | |||
| 780 | rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port); | 810 | rgmii_get_mdio(dev->rgmii_dev, dev->rgmii_port); |
| 781 | 811 | ||
| 782 | /* Wait for management interface to be idle */ | 812 | /* Wait for management interface to be idle */ |
| 783 | n = 10; | 813 | n = 20; |
| 784 | while (!emac_phy_done(dev, in_be32(&p->stacr))) { | 814 | while (!emac_phy_done(dev, in_be32(&p->stacr))) { |
| 785 | udelay(1); | 815 | udelay(1); |
| 786 | if (!--n) { | 816 | if (!--n) { |
| @@ -806,7 +836,7 @@ static void __emac_mdio_write(struct emac_instance *dev, u8 id, u8 reg, | |||
| 806 | out_be32(&p->stacr, r); | 836 | out_be32(&p->stacr, r); |
| 807 | 837 | ||
| 808 | /* Wait for write to complete */ | 838 | /* Wait for write to complete */ |
| 809 | n = 100; | 839 | n = 200; |
| 810 | while (!emac_phy_done(dev, in_be32(&p->stacr))) { | 840 | while (!emac_phy_done(dev, in_be32(&p->stacr))) { |
| 811 | udelay(1); | 841 | udelay(1); |
| 812 | if (!--n) { | 842 | if (!--n) { |
| @@ -1094,9 +1124,11 @@ static int emac_open(struct net_device *ndev) | |||
| 1094 | int link_poll_interval; | 1124 | int link_poll_interval; |
| 1095 | if (dev->phy.def->ops->poll_link(&dev->phy)) { | 1125 | if (dev->phy.def->ops->poll_link(&dev->phy)) { |
| 1096 | dev->phy.def->ops->read_link(&dev->phy); | 1126 | dev->phy.def->ops->read_link(&dev->phy); |
| 1127 | emac_rx_clk_default(dev); | ||
| 1097 | netif_carrier_on(dev->ndev); | 1128 | netif_carrier_on(dev->ndev); |
| 1098 | link_poll_interval = PHY_POLL_LINK_ON; | 1129 | link_poll_interval = PHY_POLL_LINK_ON; |
| 1099 | } else { | 1130 | } else { |
| 1131 | emac_rx_clk_tx(dev); | ||
| 1100 | netif_carrier_off(dev->ndev); | 1132 | netif_carrier_off(dev->ndev); |
| 1101 | link_poll_interval = PHY_POLL_LINK_OFF; | 1133 | link_poll_interval = PHY_POLL_LINK_OFF; |
| 1102 | } | 1134 | } |
| @@ -1174,6 +1206,7 @@ static void emac_link_timer(struct work_struct *work) | |||
| 1174 | 1206 | ||
| 1175 | if (dev->phy.def->ops->poll_link(&dev->phy)) { | 1207 | if (dev->phy.def->ops->poll_link(&dev->phy)) { |
| 1176 | if (!netif_carrier_ok(dev->ndev)) { | 1208 | if (!netif_carrier_ok(dev->ndev)) { |
| 1209 | emac_rx_clk_default(dev); | ||
| 1177 | /* Get new link parameters */ | 1210 | /* Get new link parameters */ |
| 1178 | dev->phy.def->ops->read_link(&dev->phy); | 1211 | dev->phy.def->ops->read_link(&dev->phy); |
| 1179 | 1212 | ||
| @@ -1186,6 +1219,7 @@ static void emac_link_timer(struct work_struct *work) | |||
| 1186 | link_poll_interval = PHY_POLL_LINK_ON; | 1219 | link_poll_interval = PHY_POLL_LINK_ON; |
| 1187 | } else { | 1220 | } else { |
| 1188 | if (netif_carrier_ok(dev->ndev)) { | 1221 | if (netif_carrier_ok(dev->ndev)) { |
| 1222 | emac_rx_clk_tx(dev); | ||
| 1189 | netif_carrier_off(dev->ndev); | 1223 | netif_carrier_off(dev->ndev); |
| 1190 | netif_tx_disable(dev->ndev); | 1224 | netif_tx_disable(dev->ndev); |
| 1191 | emac_reinitialize(dev); | 1225 | emac_reinitialize(dev); |
| @@ -2237,7 +2271,7 @@ static int __devinit emac_of_bus_notify(struct notifier_block *nb, | |||
| 2237 | return 0; | 2271 | return 0; |
| 2238 | } | 2272 | } |
| 2239 | 2273 | ||
| 2240 | static struct notifier_block emac_of_bus_notifier = { | 2274 | static struct notifier_block emac_of_bus_notifier __devinitdata = { |
| 2241 | .notifier_call = emac_of_bus_notify | 2275 | .notifier_call = emac_of_bus_notify |
| 2242 | }; | 2276 | }; |
| 2243 | 2277 | ||
| @@ -2330,6 +2364,19 @@ static int __devinit emac_init_phy(struct emac_instance *dev) | |||
| 2330 | dev->phy.mdio_read = emac_mdio_read; | 2364 | dev->phy.mdio_read = emac_mdio_read; |
| 2331 | dev->phy.mdio_write = emac_mdio_write; | 2365 | dev->phy.mdio_write = emac_mdio_write; |
| 2332 | 2366 | ||
| 2367 | /* Enable internal clock source */ | ||
| 2368 | #ifdef CONFIG_PPC_DCR_NATIVE | ||
| 2369 | if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX)) | ||
| 2370 | dcri_clrset(SDR0, SDR0_MFR, 0, SDR0_MFR_ECS); | ||
| 2371 | #endif | ||
| 2372 | /* PHY clock workaround */ | ||
| 2373 | emac_rx_clk_tx(dev); | ||
| 2374 | |||
| 2375 | /* Enable internal clock source on 440GX*/ | ||
| 2376 | #ifdef CONFIG_PPC_DCR_NATIVE | ||
| 2377 | if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX)) | ||
| 2378 | dcri_clrset(SDR0, SDR0_MFR, 0, SDR0_MFR_ECS); | ||
| 2379 | #endif | ||
| 2333 | /* Configure EMAC with defaults so we can at least use MDIO | 2380 | /* Configure EMAC with defaults so we can at least use MDIO |
| 2334 | * This is needed mostly for 440GX | 2381 | * This is needed mostly for 440GX |
| 2335 | */ | 2382 | */ |
| @@ -2362,6 +2409,12 @@ static int __devinit emac_init_phy(struct emac_instance *dev) | |||
| 2362 | if (!emac_mii_phy_probe(&dev->phy, i)) | 2409 | if (!emac_mii_phy_probe(&dev->phy, i)) |
| 2363 | break; | 2410 | break; |
| 2364 | } | 2411 | } |
| 2412 | |||
| 2413 | /* Enable external clock source */ | ||
| 2414 | #ifdef CONFIG_PPC_DCR_NATIVE | ||
| 2415 | if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX)) | ||
| 2416 | dcri_clrset(SDR0, SDR0_MFR, SDR0_MFR_ECS, 0); | ||
| 2417 | #endif | ||
| 2365 | mutex_unlock(&emac_phy_map_lock); | 2418 | mutex_unlock(&emac_phy_map_lock); |
| 2366 | if (i == 0x20) { | 2419 | if (i == 0x20) { |
| 2367 | printk(KERN_WARNING "%s: can't find PHY!\n", np->full_name); | 2420 | printk(KERN_WARNING "%s: can't find PHY!\n", np->full_name); |
| @@ -2487,8 +2540,15 @@ static int __devinit emac_init_config(struct emac_instance *dev) | |||
| 2487 | } | 2540 | } |
| 2488 | 2541 | ||
| 2489 | /* Check EMAC version */ | 2542 | /* Check EMAC version */ |
| 2490 | if (of_device_is_compatible(np, "ibm,emac4")) | 2543 | if (of_device_is_compatible(np, "ibm,emac4")) { |
| 2491 | dev->features |= EMAC_FTR_EMAC4; | 2544 | dev->features |= EMAC_FTR_EMAC4; |
| 2545 | if (of_device_is_compatible(np, "ibm,emac-440gx")) | ||
| 2546 | dev->features |= EMAC_FTR_440GX_PHY_CLK_FIX; | ||
| 2547 | } else { | ||
| 2548 | if (of_device_is_compatible(np, "ibm,emac-440ep") || | ||
| 2549 | of_device_is_compatible(np, "ibm,emac-440gr")) | ||
| 2550 | dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX; | ||
| 2551 | } | ||
| 2492 | 2552 | ||
| 2493 | /* Fixup some feature bits based on the device tree */ | 2553 | /* Fixup some feature bits based on the device tree */ |
| 2494 | if (of_get_property(np, "has-inverted-stacr-oc", NULL)) | 2554 | if (of_get_property(np, "has-inverted-stacr-oc", NULL)) |
| @@ -2559,8 +2619,11 @@ static int __devinit emac_probe(struct of_device *ofdev, | |||
| 2559 | struct device_node **blist = NULL; | 2619 | struct device_node **blist = NULL; |
| 2560 | int err, i; | 2620 | int err, i; |
| 2561 | 2621 | ||
| 2562 | /* Skip unused/unwired EMACS */ | 2622 | /* Skip unused/unwired EMACS. We leave the check for an unused |
| 2563 | if (of_get_property(np, "unused", NULL)) | 2623 | * property here for now, but new flat device trees should set a |
| 2624 | * status property to "disabled" instead. | ||
| 2625 | */ | ||
| 2626 | if (of_get_property(np, "unused", NULL) || !of_device_is_available(np)) | ||
| 2564 | return -ENODEV; | 2627 | return -ENODEV; |
| 2565 | 2628 | ||
| 2566 | /* Find ourselves in the bootlist if we are there */ | 2629 | /* Find ourselves in the bootlist if we are there */ |
diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h index 4e74d8287c65..1683db9870a4 100644 --- a/drivers/net/ibm_newemac/core.h +++ b/drivers/net/ibm_newemac/core.h | |||
| @@ -301,6 +301,14 @@ struct emac_instance { | |||
| 301 | * Set if we have new type STACR with STAOPC | 301 | * Set if we have new type STACR with STAOPC |
| 302 | */ | 302 | */ |
| 303 | #define EMAC_FTR_HAS_NEW_STACR 0x00000040 | 303 | #define EMAC_FTR_HAS_NEW_STACR 0x00000040 |
| 304 | /* | ||
| 305 | * Set if we need phy clock workaround for 440gx | ||
| 306 | */ | ||
| 307 | #define EMAC_FTR_440GX_PHY_CLK_FIX 0x00000080 | ||
| 308 | /* | ||
| 309 | * Set if we need phy clock workaround for 440ep or 440gr | ||
| 310 | */ | ||
| 311 | #define EMAC_FTR_440EP_PHY_CLK_FIX 0x00000100 | ||
| 304 | 312 | ||
| 305 | 313 | ||
| 306 | /* Right now, we don't quite handle the always/possible masks on the | 314 | /* Right now, we don't quite handle the always/possible masks on the |
| @@ -312,8 +320,8 @@ enum { | |||
| 312 | 320 | ||
| 313 | EMAC_FTRS_POSSIBLE = | 321 | EMAC_FTRS_POSSIBLE = |
| 314 | #ifdef CONFIG_IBM_NEW_EMAC_EMAC4 | 322 | #ifdef CONFIG_IBM_NEW_EMAC_EMAC4 |
| 315 | EMAC_FTR_EMAC4 | EMAC_FTR_HAS_NEW_STACR | | 323 | EMAC_FTR_EMAC4 | EMAC_FTR_HAS_NEW_STACR | |
| 316 | EMAC_FTR_STACR_OC_INVERT | | 324 | EMAC_FTR_STACR_OC_INVERT | EMAC_FTR_440GX_PHY_CLK_FIX | |
| 317 | #endif | 325 | #endif |
| 318 | #ifdef CONFIG_IBM_NEW_EMAC_TAH | 326 | #ifdef CONFIG_IBM_NEW_EMAC_TAH |
| 319 | EMAC_FTR_HAS_TAH | | 327 | EMAC_FTR_HAS_TAH | |
| @@ -324,7 +332,7 @@ enum { | |||
| 324 | #ifdef CONFIG_IBM_NEW_EMAC_RGMII | 332 | #ifdef CONFIG_IBM_NEW_EMAC_RGMII |
| 325 | EMAC_FTR_HAS_RGMII | | 333 | EMAC_FTR_HAS_RGMII | |
| 326 | #endif | 334 | #endif |
| 327 | 0, | 335 | EMAC_FTR_440EP_PHY_CLK_FIX, |
| 328 | }; | 336 | }; |
| 329 | 337 | ||
| 330 | static inline int emac_has_feature(struct emac_instance *dev, | 338 | static inline int emac_has_feature(struct emac_instance *dev, |
diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c index 6869f08c9dcb..10c267b2b961 100644 --- a/drivers/net/ibm_newemac/mal.c +++ b/drivers/net/ibm_newemac/mal.c | |||
| @@ -61,8 +61,8 @@ int __devinit mal_register_commac(struct mal_instance *mal, | |||
| 61 | return 0; | 61 | return 0; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | void __devexit mal_unregister_commac(struct mal_instance *mal, | 64 | void mal_unregister_commac(struct mal_instance *mal, |
| 65 | struct mal_commac *commac) | 65 | struct mal_commac *commac) |
| 66 | { | 66 | { |
| 67 | unsigned long flags; | 67 | unsigned long flags; |
| 68 | 68 | ||
| @@ -136,6 +136,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel) | |||
| 136 | { | 136 | { |
| 137 | unsigned long flags; | 137 | unsigned long flags; |
| 138 | 138 | ||
| 139 | /* | ||
| 140 | * On some 4xx PPC's (e.g. 460EX/GT), the rx channel is a multiple | ||
| 141 | * of 8, but enabling in MAL_RXCASR needs the divided by 8 value | ||
| 142 | * for the bitmask | ||
| 143 | */ | ||
| 144 | if (!(channel % 8)) | ||
| 145 | channel >>= 3; | ||
| 146 | |||
| 139 | spin_lock_irqsave(&mal->lock, flags); | 147 | spin_lock_irqsave(&mal->lock, flags); |
| 140 | 148 | ||
| 141 | MAL_DBG(mal, "enable_rx(%d)" NL, channel); | 149 | MAL_DBG(mal, "enable_rx(%d)" NL, channel); |
| @@ -148,6 +156,14 @@ void mal_enable_rx_channel(struct mal_instance *mal, int channel) | |||
| 148 | 156 | ||
| 149 | void mal_disable_rx_channel(struct mal_instance *mal, int channel) | 157 | void mal_disable_rx_channel(struct mal_instance *mal, int channel) |
| 150 | { | 158 | { |
| 159 | /* | ||
| 160 | * On some 4xx PPC's (e.g. 460EX/GT), the rx channel is a multiple | ||
| 161 | * of 8, but enabling in MAL_RXCASR needs the divided by 8 value | ||
| 162 | * for the bitmask | ||
| 163 | */ | ||
| 164 | if (!(channel % 8)) | ||
| 165 | channel >>= 3; | ||
| 166 | |||
| 151 | set_mal_dcrn(mal, MAL_RXCARR, MAL_CHAN_MASK(channel)); | 167 | set_mal_dcrn(mal, MAL_RXCARR, MAL_CHAN_MASK(channel)); |
| 152 | 168 | ||
| 153 | MAL_DBG(mal, "disable_rx(%d)" NL, channel); | 169 | MAL_DBG(mal, "disable_rx(%d)" NL, channel); |
diff --git a/drivers/net/ibm_newemac/rgmii.c b/drivers/net/ibm_newemac/rgmii.c index 5757788227be..e32da3de2695 100644 --- a/drivers/net/ibm_newemac/rgmii.c +++ b/drivers/net/ibm_newemac/rgmii.c | |||
| @@ -179,7 +179,7 @@ void rgmii_put_mdio(struct of_device *ofdev, int input) | |||
| 179 | mutex_unlock(&dev->lock); | 179 | mutex_unlock(&dev->lock); |
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | void __devexit rgmii_detach(struct of_device *ofdev, int input) | 182 | void rgmii_detach(struct of_device *ofdev, int input) |
| 183 | { | 183 | { |
| 184 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 184 | struct rgmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
| 185 | struct rgmii_regs __iomem *p = dev->base; | 185 | struct rgmii_regs __iomem *p = dev->base; |
diff --git a/drivers/net/ibm_newemac/tah.c b/drivers/net/ibm_newemac/tah.c index b023d10d7e1c..30173a9fb557 100644 --- a/drivers/net/ibm_newemac/tah.c +++ b/drivers/net/ibm_newemac/tah.c | |||
| @@ -35,7 +35,7 @@ int __devinit tah_attach(struct of_device *ofdev, int channel) | |||
| 35 | return 0; | 35 | return 0; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | void __devexit tah_detach(struct of_device *ofdev, int channel) | 38 | void tah_detach(struct of_device *ofdev, int channel) |
| 39 | { | 39 | { |
| 40 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); | 40 | struct tah_instance *dev = dev_get_drvdata(&ofdev->dev); |
| 41 | 41 | ||
diff --git a/drivers/net/ibm_newemac/zmii.c b/drivers/net/ibm_newemac/zmii.c index 2ea472aeab06..17b154124943 100644 --- a/drivers/net/ibm_newemac/zmii.c +++ b/drivers/net/ibm_newemac/zmii.c | |||
| @@ -189,7 +189,7 @@ void zmii_set_speed(struct of_device *ofdev, int input, int speed) | |||
| 189 | mutex_unlock(&dev->lock); | 189 | mutex_unlock(&dev->lock); |
| 190 | } | 190 | } |
| 191 | 191 | ||
| 192 | void __devexit zmii_detach(struct of_device *ofdev, int input) | 192 | void zmii_detach(struct of_device *ofdev, int input) |
| 193 | { | 193 | { |
| 194 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); | 194 | struct zmii_instance *dev = dev_get_drvdata(&ofdev->dev); |
| 195 | 195 | ||
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index aaee02e9e3f0..ae398f04c7b4 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c | |||
| @@ -871,6 +871,7 @@ static int __devinit igb_probe(struct pci_dev *pdev, | |||
| 871 | goto err_pci_reg; | 871 | goto err_pci_reg; |
| 872 | 872 | ||
| 873 | pci_set_master(pdev); | 873 | pci_set_master(pdev); |
| 874 | pci_save_state(pdev); | ||
| 874 | 875 | ||
| 875 | err = -ENOMEM; | 876 | err = -ENOMEM; |
| 876 | netdev = alloc_etherdev(sizeof(struct igb_adapter)); | 877 | netdev = alloc_etherdev(sizeof(struct igb_adapter)); |
| @@ -4079,6 +4080,7 @@ static pci_ers_result_t igb_io_slot_reset(struct pci_dev *pdev) | |||
| 4079 | return PCI_ERS_RESULT_DISCONNECT; | 4080 | return PCI_ERS_RESULT_DISCONNECT; |
| 4080 | } | 4081 | } |
| 4081 | pci_set_master(pdev); | 4082 | pci_set_master(pdev); |
| 4083 | pci_restore_state(pdev); | ||
| 4082 | 4084 | ||
| 4083 | pci_enable_wake(pdev, PCI_D3hot, 0); | 4085 | pci_enable_wake(pdev, PCI_D3hot, 0); |
| 4084 | pci_enable_wake(pdev, PCI_D3cold, 0); | 4086 | pci_enable_wake(pdev, PCI_D3cold, 0); |
diff --git a/drivers/net/irda/ali-ircc.c b/drivers/net/irda/ali-ircc.c index 9f584521304a..083b0dd70fef 100644 --- a/drivers/net/irda/ali-ircc.c +++ b/drivers/net/irda/ali-ircc.c | |||
| @@ -60,6 +60,7 @@ static struct platform_driver ali_ircc_driver = { | |||
| 60 | .resume = ali_ircc_resume, | 60 | .resume = ali_ircc_resume, |
| 61 | .driver = { | 61 | .driver = { |
| 62 | .name = ALI_IRCC_DRIVER_NAME, | 62 | .name = ALI_IRCC_DRIVER_NAME, |
| 63 | .owner = THIS_MODULE, | ||
| 63 | }, | 64 | }, |
| 64 | }; | 65 | }; |
| 65 | 66 | ||
| @@ -2256,6 +2257,7 @@ static void FIR2SIR(int iobase) | |||
| 2256 | MODULE_AUTHOR("Benjamin Kong <benjamin_kong@ali.com.tw>"); | 2257 | MODULE_AUTHOR("Benjamin Kong <benjamin_kong@ali.com.tw>"); |
| 2257 | MODULE_DESCRIPTION("ALi FIR Controller Driver"); | 2258 | MODULE_DESCRIPTION("ALi FIR Controller Driver"); |
| 2258 | MODULE_LICENSE("GPL"); | 2259 | MODULE_LICENSE("GPL"); |
| 2260 | MODULE_ALIAS("platform:" ALI_IRCC_DRIVER_NAME); | ||
| 2259 | 2261 | ||
| 2260 | 2262 | ||
| 2261 | module_param_array(io, int, NULL, 0); | 2263 | module_param_array(io, int, NULL, 0); |
diff --git a/drivers/net/irda/pxaficp_ir.c b/drivers/net/irda/pxaficp_ir.c index 8db71ab20456..d5c2d27f3ea4 100644 --- a/drivers/net/irda/pxaficp_ir.c +++ b/drivers/net/irda/pxaficp_ir.c | |||
| @@ -908,6 +908,7 @@ static int pxa_irda_remove(struct platform_device *_dev) | |||
| 908 | static struct platform_driver pxa_ir_driver = { | 908 | static struct platform_driver pxa_ir_driver = { |
| 909 | .driver = { | 909 | .driver = { |
| 910 | .name = "pxa2xx-ir", | 910 | .name = "pxa2xx-ir", |
| 911 | .owner = THIS_MODULE, | ||
| 911 | }, | 912 | }, |
| 912 | .probe = pxa_irda_probe, | 913 | .probe = pxa_irda_probe, |
| 913 | .remove = pxa_irda_remove, | 914 | .remove = pxa_irda_remove, |
| @@ -929,3 +930,4 @@ module_init(pxa_irda_init); | |||
| 929 | module_exit(pxa_irda_exit); | 930 | module_exit(pxa_irda_exit); |
| 930 | 931 | ||
| 931 | MODULE_LICENSE("GPL"); | 932 | MODULE_LICENSE("GPL"); |
| 933 | MODULE_ALIAS("platform:pxa2xx-ir"); | ||
diff --git a/drivers/net/irda/sa1100_ir.c b/drivers/net/irda/sa1100_ir.c index 056639f72bec..1bc8518f9197 100644 --- a/drivers/net/irda/sa1100_ir.c +++ b/drivers/net/irda/sa1100_ir.c | |||
| @@ -1008,6 +1008,7 @@ static struct platform_driver sa1100ir_driver = { | |||
| 1008 | .resume = sa1100_irda_resume, | 1008 | .resume = sa1100_irda_resume, |
| 1009 | .driver = { | 1009 | .driver = { |
| 1010 | .name = "sa11x0-ir", | 1010 | .name = "sa11x0-ir", |
| 1011 | .owner = THIS_MODULE, | ||
| 1011 | }, | 1012 | }, |
| 1012 | }; | 1013 | }; |
| 1013 | 1014 | ||
| @@ -1041,3 +1042,4 @@ MODULE_LICENSE("GPL"); | |||
| 1041 | MODULE_PARM_DESC(power_level, "IrDA power level, 1 (low) to 3 (high)"); | 1042 | MODULE_PARM_DESC(power_level, "IrDA power level, 1 (low) to 3 (high)"); |
| 1042 | MODULE_PARM_DESC(tx_lpm, "Enable transmitter low power (1.6us) mode"); | 1043 | MODULE_PARM_DESC(tx_lpm, "Enable transmitter low power (1.6us) mode"); |
| 1043 | MODULE_PARM_DESC(max_rate, "Maximum baud rate (4000000, 115200, 57600, 38400, 19200, 9600)"); | 1044 | MODULE_PARM_DESC(max_rate, "Maximum baud rate (4000000, 115200, 57600, 38400, 19200, 9600)"); |
| 1045 | MODULE_ALIAS("platform:sa11x0-ir"); | ||
diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index cb371a8c24a7..7b859220c255 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c | |||
| @@ -3431,6 +3431,7 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev, | |||
| 3431 | } | 3431 | } |
| 3432 | 3432 | ||
| 3433 | pci_set_master(pdev); | 3433 | pci_set_master(pdev); |
| 3434 | pci_save_state(pdev); | ||
| 3434 | 3435 | ||
| 3435 | #ifdef CONFIG_NETDEVICES_MULTIQUEUE | 3436 | #ifdef CONFIG_NETDEVICES_MULTIQUEUE |
| 3436 | netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), MAX_TX_QUEUES); | 3437 | netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), MAX_TX_QUEUES); |
| @@ -3721,6 +3722,7 @@ static pci_ers_result_t ixgbe_io_slot_reset(struct pci_dev *pdev) | |||
| 3721 | return PCI_ERS_RESULT_DISCONNECT; | 3722 | return PCI_ERS_RESULT_DISCONNECT; |
| 3722 | } | 3723 | } |
| 3723 | pci_set_master(pdev); | 3724 | pci_set_master(pdev); |
| 3725 | pci_restore_state(pdev); | ||
| 3724 | 3726 | ||
| 3725 | pci_enable_wake(pdev, PCI_D3hot, 0); | 3727 | pci_enable_wake(pdev, PCI_D3hot, 0); |
| 3726 | pci_enable_wake(pdev, PCI_D3cold, 0); | 3728 | pci_enable_wake(pdev, PCI_D3cold, 0); |
diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c index 5c154fe13859..07944820f745 100644 --- a/drivers/net/jazzsonic.c +++ b/drivers/net/jazzsonic.c | |||
| @@ -249,6 +249,7 @@ out: | |||
| 249 | MODULE_DESCRIPTION("Jazz SONIC ethernet driver"); | 249 | MODULE_DESCRIPTION("Jazz SONIC ethernet driver"); |
| 250 | module_param(sonic_debug, int, 0); | 250 | module_param(sonic_debug, int, 0); |
| 251 | MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)"); | 251 | MODULE_PARM_DESC(sonic_debug, "jazzsonic debug level (1-4)"); |
| 252 | MODULE_ALIAS("platform:jazzsonic"); | ||
| 252 | 253 | ||
| 253 | #include "sonic.c" | 254 | #include "sonic.c" |
| 254 | 255 | ||
| @@ -271,6 +272,7 @@ static struct platform_driver jazz_sonic_driver = { | |||
| 271 | .remove = __devexit_p(jazz_sonic_device_remove), | 272 | .remove = __devexit_p(jazz_sonic_device_remove), |
| 272 | .driver = { | 273 | .driver = { |
| 273 | .name = jazz_sonic_string, | 274 | .name = jazz_sonic_string, |
| 275 | .owner = THIS_MODULE, | ||
| 274 | }, | 276 | }, |
| 275 | }; | 277 | }; |
| 276 | 278 | ||
diff --git a/drivers/net/korina.c b/drivers/net/korina.c index 1d24a73a0e1a..e18576316bda 100644 --- a/drivers/net/korina.c +++ b/drivers/net/korina.c | |||
| @@ -883,7 +883,7 @@ static int korina_init(struct net_device *dev) | |||
| 883 | static int korina_restart(struct net_device *dev) | 883 | static int korina_restart(struct net_device *dev) |
| 884 | { | 884 | { |
| 885 | struct korina_private *lp = netdev_priv(dev); | 885 | struct korina_private *lp = netdev_priv(dev); |
| 886 | int ret = 0; | 886 | int ret; |
| 887 | 887 | ||
| 888 | /* | 888 | /* |
| 889 | * Disable interrupts | 889 | * Disable interrupts |
| @@ -987,7 +987,7 @@ static void korina_poll_controller(struct net_device *dev) | |||
| 987 | static int korina_open(struct net_device *dev) | 987 | static int korina_open(struct net_device *dev) |
| 988 | { | 988 | { |
| 989 | struct korina_private *lp = netdev_priv(dev); | 989 | struct korina_private *lp = netdev_priv(dev); |
| 990 | int ret = 0; | 990 | int ret; |
| 991 | 991 | ||
| 992 | /* Initialize */ | 992 | /* Initialize */ |
| 993 | ret = korina_init(dev); | 993 | ret = korina_init(dev); |
| @@ -1031,6 +1031,8 @@ static int korina_open(struct net_device *dev) | |||
| 1031 | dev->name, lp->und_irq); | 1031 | dev->name, lp->und_irq); |
| 1032 | goto err_free_ovr_irq; | 1032 | goto err_free_ovr_irq; |
| 1033 | } | 1033 | } |
| 1034 | out: | ||
| 1035 | return ret; | ||
| 1034 | 1036 | ||
| 1035 | err_free_ovr_irq: | 1037 | err_free_ovr_irq: |
| 1036 | free_irq(lp->ovr_irq, dev); | 1038 | free_irq(lp->ovr_irq, dev); |
| @@ -1041,8 +1043,6 @@ err_free_rx_irq: | |||
| 1041 | err_release: | 1043 | err_release: |
| 1042 | korina_free_ring(dev); | 1044 | korina_free_ring(dev); |
| 1043 | goto out; | 1045 | goto out; |
| 1044 | out: | ||
| 1045 | return ret; | ||
| 1046 | } | 1046 | } |
| 1047 | 1047 | ||
| 1048 | static int korina_close(struct net_device *dev) | 1048 | static int korina_close(struct net_device *dev) |
| @@ -1082,7 +1082,7 @@ static int korina_probe(struct platform_device *pdev) | |||
| 1082 | struct korina_private *lp; | 1082 | struct korina_private *lp; |
| 1083 | struct net_device *dev; | 1083 | struct net_device *dev; |
| 1084 | struct resource *r; | 1084 | struct resource *r; |
| 1085 | int retval, err; | 1085 | int rc; |
| 1086 | 1086 | ||
| 1087 | dev = alloc_etherdev(sizeof(struct korina_private)); | 1087 | dev = alloc_etherdev(sizeof(struct korina_private)); |
| 1088 | if (!dev) { | 1088 | if (!dev) { |
| @@ -1106,7 +1106,7 @@ static int korina_probe(struct platform_device *pdev) | |||
| 1106 | lp->eth_regs = ioremap_nocache(r->start, r->end - r->start); | 1106 | lp->eth_regs = ioremap_nocache(r->start, r->end - r->start); |
| 1107 | if (!lp->eth_regs) { | 1107 | if (!lp->eth_regs) { |
| 1108 | printk(KERN_ERR DRV_NAME "cannot remap registers\n"); | 1108 | printk(KERN_ERR DRV_NAME "cannot remap registers\n"); |
| 1109 | retval = -ENXIO; | 1109 | rc = -ENXIO; |
| 1110 | goto probe_err_out; | 1110 | goto probe_err_out; |
| 1111 | } | 1111 | } |
| 1112 | 1112 | ||
| @@ -1114,7 +1114,7 @@ static int korina_probe(struct platform_device *pdev) | |||
| 1114 | lp->rx_dma_regs = ioremap_nocache(r->start, r->end - r->start); | 1114 | lp->rx_dma_regs = ioremap_nocache(r->start, r->end - r->start); |
| 1115 | if (!lp->rx_dma_regs) { | 1115 | if (!lp->rx_dma_regs) { |
| 1116 | printk(KERN_ERR DRV_NAME "cannot remap Rx DMA registers\n"); | 1116 | printk(KERN_ERR DRV_NAME "cannot remap Rx DMA registers\n"); |
| 1117 | retval = -ENXIO; | 1117 | rc = -ENXIO; |
| 1118 | goto probe_err_dma_rx; | 1118 | goto probe_err_dma_rx; |
| 1119 | } | 1119 | } |
| 1120 | 1120 | ||
| @@ -1122,14 +1122,14 @@ static int korina_probe(struct platform_device *pdev) | |||
| 1122 | lp->tx_dma_regs = ioremap_nocache(r->start, r->end - r->start); | 1122 | lp->tx_dma_regs = ioremap_nocache(r->start, r->end - r->start); |
| 1123 | if (!lp->tx_dma_regs) { | 1123 | if (!lp->tx_dma_regs) { |
| 1124 | printk(KERN_ERR DRV_NAME "cannot remap Tx DMA registers\n"); | 1124 | printk(KERN_ERR DRV_NAME "cannot remap Tx DMA registers\n"); |
| 1125 | retval = -ENXIO; | 1125 | rc = -ENXIO; |
| 1126 | goto probe_err_dma_tx; | 1126 | goto probe_err_dma_tx; |
| 1127 | } | 1127 | } |
| 1128 | 1128 | ||
| 1129 | lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL); | 1129 | lp->td_ring = kmalloc(TD_RING_SIZE + RD_RING_SIZE, GFP_KERNEL); |
| 1130 | if (!lp->td_ring) { | 1130 | if (!lp->td_ring) { |
| 1131 | printk(KERN_ERR DRV_NAME "cannot allocate descriptors\n"); | 1131 | printk(KERN_ERR DRV_NAME "cannot allocate descriptors\n"); |
| 1132 | retval = -ENOMEM; | 1132 | rc = -ENXIO; |
| 1133 | goto probe_err_td_ring; | 1133 | goto probe_err_td_ring; |
| 1134 | } | 1134 | } |
| 1135 | 1135 | ||
| @@ -1166,14 +1166,14 @@ static int korina_probe(struct platform_device *pdev) | |||
| 1166 | lp->mii_if.phy_id_mask = 0x1f; | 1166 | lp->mii_if.phy_id_mask = 0x1f; |
| 1167 | lp->mii_if.reg_num_mask = 0x1f; | 1167 | lp->mii_if.reg_num_mask = 0x1f; |
| 1168 | 1168 | ||
| 1169 | err = register_netdev(dev); | 1169 | rc = register_netdev(dev); |
| 1170 | if (err) { | 1170 | if (rc < 0) { |
| 1171 | printk(KERN_ERR DRV_NAME | 1171 | printk(KERN_ERR DRV_NAME |
| 1172 | ": cannot register net device %d\n", err); | 1172 | ": cannot register net device %d\n", rc); |
| 1173 | retval = -EINVAL; | ||
| 1174 | goto probe_err_register; | 1173 | goto probe_err_register; |
| 1175 | } | 1174 | } |
| 1176 | return 0; | 1175 | out: |
| 1176 | return rc; | ||
| 1177 | 1177 | ||
| 1178 | probe_err_register: | 1178 | probe_err_register: |
| 1179 | kfree(lp->td_ring); | 1179 | kfree(lp->td_ring); |
| @@ -1185,7 +1185,7 @@ probe_err_dma_rx: | |||
| 1185 | iounmap(lp->eth_regs); | 1185 | iounmap(lp->eth_regs); |
| 1186 | probe_err_out: | 1186 | probe_err_out: |
| 1187 | free_netdev(dev); | 1187 | free_netdev(dev); |
| 1188 | return retval; | 1188 | goto out; |
| 1189 | } | 1189 | } |
| 1190 | 1190 | ||
| 1191 | static int korina_remove(struct platform_device *pdev) | 1191 | static int korina_remove(struct platform_device *pdev) |
| @@ -1193,12 +1193,9 @@ static int korina_remove(struct platform_device *pdev) | |||
| 1193 | struct korina_device *bif = platform_get_drvdata(pdev); | 1193 | struct korina_device *bif = platform_get_drvdata(pdev); |
| 1194 | struct korina_private *lp = netdev_priv(bif->dev); | 1194 | struct korina_private *lp = netdev_priv(bif->dev); |
| 1195 | 1195 | ||
| 1196 | if (lp->eth_regs) | 1196 | iounmap(lp->eth_regs); |
| 1197 | iounmap(lp->eth_regs); | 1197 | iounmap(lp->rx_dma_regs); |
| 1198 | if (lp->rx_dma_regs) | 1198 | iounmap(lp->tx_dma_regs); |
| 1199 | iounmap(lp->rx_dma_regs); | ||
| 1200 | if (lp->tx_dma_regs) | ||
| 1201 | iounmap(lp->tx_dma_regs); | ||
| 1202 | 1199 | ||
| 1203 | platform_set_drvdata(pdev, NULL); | 1200 | platform_set_drvdata(pdev, NULL); |
| 1204 | unregister_netdev(bif->dev); | 1201 | unregister_netdev(bif->dev); |
diff --git a/drivers/net/macb.c b/drivers/net/macb.c index d513bb8a4902..92dccd43bdca 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c | |||
| @@ -1281,6 +1281,7 @@ static struct platform_driver macb_driver = { | |||
| 1281 | .remove = __exit_p(macb_remove), | 1281 | .remove = __exit_p(macb_remove), |
| 1282 | .driver = { | 1282 | .driver = { |
| 1283 | .name = "macb", | 1283 | .name = "macb", |
| 1284 | .owner = THIS_MODULE, | ||
| 1284 | }, | 1285 | }, |
| 1285 | }; | 1286 | }; |
| 1286 | 1287 | ||
| @@ -1300,3 +1301,4 @@ module_exit(macb_exit); | |||
| 1300 | MODULE_LICENSE("GPL"); | 1301 | MODULE_LICENSE("GPL"); |
| 1301 | MODULE_DESCRIPTION("Atmel MACB Ethernet driver"); | 1302 | MODULE_DESCRIPTION("Atmel MACB Ethernet driver"); |
| 1302 | MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); | 1303 | MODULE_AUTHOR("Haavard Skinnemoen <hskinnemoen@atmel.com>"); |
| 1304 | MODULE_ALIAS("platform:macb"); | ||
diff --git a/drivers/net/meth.c b/drivers/net/meth.c index cdaa8fc21809..0b32648a2136 100644 --- a/drivers/net/meth.c +++ b/drivers/net/meth.c | |||
| @@ -830,6 +830,7 @@ static struct platform_driver meth_driver = { | |||
| 830 | .remove = __devexit_p(meth_remove), | 830 | .remove = __devexit_p(meth_remove), |
| 831 | .driver = { | 831 | .driver = { |
| 832 | .name = "meth", | 832 | .name = "meth", |
| 833 | .owner = THIS_MODULE, | ||
| 833 | } | 834 | } |
| 834 | }; | 835 | }; |
| 835 | 836 | ||
| @@ -855,3 +856,4 @@ module_exit(meth_exit_module); | |||
| 855 | MODULE_AUTHOR("Ilya Volynets <ilya@theIlya.com>"); | 856 | MODULE_AUTHOR("Ilya Volynets <ilya@theIlya.com>"); |
| 856 | MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver"); | 857 | MODULE_DESCRIPTION("SGI O2 Builtin Fast Ethernet driver"); |
| 857 | MODULE_LICENSE("GPL"); | 858 | MODULE_LICENSE("GPL"); |
| 859 | MODULE_ALIAS("platform:meth"); | ||
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 601ffd69ebc8..381b36e5f64c 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
| @@ -2030,6 +2030,7 @@ static struct platform_driver mv643xx_eth_driver = { | |||
| 2030 | .shutdown = mv643xx_eth_shutdown, | 2030 | .shutdown = mv643xx_eth_shutdown, |
| 2031 | .driver = { | 2031 | .driver = { |
| 2032 | .name = MV643XX_ETH_NAME, | 2032 | .name = MV643XX_ETH_NAME, |
| 2033 | .owner = THIS_MODULE, | ||
| 2033 | }, | 2034 | }, |
| 2034 | }; | 2035 | }; |
| 2035 | 2036 | ||
| @@ -2038,6 +2039,7 @@ static struct platform_driver mv643xx_eth_shared_driver = { | |||
| 2038 | .remove = mv643xx_eth_shared_remove, | 2039 | .remove = mv643xx_eth_shared_remove, |
| 2039 | .driver = { | 2040 | .driver = { |
| 2040 | .name = MV643XX_ETH_SHARED_NAME, | 2041 | .name = MV643XX_ETH_SHARED_NAME, |
| 2042 | .owner = THIS_MODULE, | ||
| 2041 | }, | 2043 | }, |
| 2042 | }; | 2044 | }; |
| 2043 | 2045 | ||
| @@ -2085,7 +2087,8 @@ MODULE_LICENSE("GPL"); | |||
| 2085 | MODULE_AUTHOR( "Rabeeh Khoury, Assaf Hoffman, Matthew Dharm, Manish Lachwani" | 2087 | MODULE_AUTHOR( "Rabeeh Khoury, Assaf Hoffman, Matthew Dharm, Manish Lachwani" |
| 2086 | " and Dale Farnsworth"); | 2088 | " and Dale Farnsworth"); |
| 2087 | MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX"); | 2089 | MODULE_DESCRIPTION("Ethernet driver for Marvell MV643XX"); |
| 2088 | MODULE_ALIAS("platform:mv643xx_eth"); | 2090 | MODULE_ALIAS("platform:" MV643XX_ETH_NAME); |
| 2091 | MODULE_ALIAS("platform:" MV643XX_ETH_SHARED_NAME); | ||
| 2089 | 2092 | ||
| 2090 | /* | 2093 | /* |
| 2091 | * The second part is the low level driver of the gigE ethernet ports. | 2094 | * The second part is the low level driver of the gigE ethernet ports. |
diff --git a/drivers/net/netx-eth.c b/drivers/net/netx-eth.c index 78d34af13a1c..dc442e370850 100644 --- a/drivers/net/netx-eth.c +++ b/drivers/net/netx-eth.c | |||
| @@ -502,4 +502,4 @@ module_exit(netx_eth_cleanup); | |||
| 502 | 502 | ||
| 503 | MODULE_AUTHOR("Sascha Hauer, Pengutronix"); | 503 | MODULE_AUTHOR("Sascha Hauer, Pengutronix"); |
| 504 | MODULE_LICENSE("GPL"); | 504 | MODULE_LICENSE("GPL"); |
| 505 | 505 | MODULE_ALIAS("platform:" CARDNAME); | |
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 05748ca6f216..af7356468251 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c | |||
| @@ -1132,8 +1132,8 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter) | |||
| 1132 | u32 fw_minor = 0; | 1132 | u32 fw_minor = 0; |
| 1133 | u32 fw_build = 0; | 1133 | u32 fw_build = 0; |
| 1134 | char brd_name[NETXEN_MAX_SHORT_NAME]; | 1134 | char brd_name[NETXEN_MAX_SHORT_NAME]; |
| 1135 | struct netxen_new_user_info user_info; | 1135 | char serial_num[32]; |
| 1136 | int i, addr = NETXEN_USER_START; | 1136 | int i, addr; |
| 1137 | __le32 *ptr32; | 1137 | __le32 *ptr32; |
| 1138 | 1138 | ||
| 1139 | struct netxen_board_info *board_info = &(adapter->ahw.boardcfg); | 1139 | struct netxen_board_info *board_info = &(adapter->ahw.boardcfg); |
| @@ -1150,10 +1150,10 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter) | |||
| 1150 | valid = 0; | 1150 | valid = 0; |
| 1151 | } | 1151 | } |
| 1152 | if (valid) { | 1152 | if (valid) { |
| 1153 | ptr32 = (u32 *) & user_info; | 1153 | ptr32 = (u32 *)&serial_num; |
| 1154 | for (i = 0; | 1154 | addr = NETXEN_USER_START + |
| 1155 | i < sizeof(struct netxen_new_user_info) / sizeof(u32); | 1155 | offsetof(struct netxen_new_user_info, serial_num); |
| 1156 | i++) { | 1156 | for (i = 0; i < 8; i++) { |
| 1157 | if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) { | 1157 | if (netxen_rom_fast_read(adapter, addr, ptr32) == -1) { |
| 1158 | printk("%s: ERROR reading %s board userarea.\n", | 1158 | printk("%s: ERROR reading %s board userarea.\n", |
| 1159 | netxen_nic_driver_name, | 1159 | netxen_nic_driver_name, |
| @@ -1163,10 +1163,11 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter) | |||
| 1163 | ptr32++; | 1163 | ptr32++; |
| 1164 | addr += sizeof(u32); | 1164 | addr += sizeof(u32); |
| 1165 | } | 1165 | } |
| 1166 | |||
| 1166 | get_brd_name_by_type(board_info->board_type, brd_name); | 1167 | get_brd_name_by_type(board_info->board_type, brd_name); |
| 1167 | 1168 | ||
| 1168 | printk("NetXen %s Board S/N %s Chip id 0x%x\n", | 1169 | printk("NetXen %s Board S/N %s Chip id 0x%x\n", |
| 1169 | brd_name, user_info.serial_num, board_info->chip_id); | 1170 | brd_name, serial_num, board_info->chip_id); |
| 1170 | 1171 | ||
| 1171 | printk("NetXen %s Board #%d, Chip id 0x%x\n", | 1172 | printk("NetXen %s Board #%d, Chip id 0x%x\n", |
| 1172 | board_info->board_type == 0x0b ? "XGB" : "GBE", | 1173 | board_info->board_type == 0x0b ? "XGB" : "GBE", |
diff --git a/drivers/net/niu.c b/drivers/net/niu.c index 7565c2d7f30e..4009c4ce96b4 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c | |||
| @@ -33,8 +33,8 @@ | |||
| 33 | 33 | ||
| 34 | #define DRV_MODULE_NAME "niu" | 34 | #define DRV_MODULE_NAME "niu" |
| 35 | #define PFX DRV_MODULE_NAME ": " | 35 | #define PFX DRV_MODULE_NAME ": " |
| 36 | #define DRV_MODULE_VERSION "0.7" | 36 | #define DRV_MODULE_VERSION "0.8" |
| 37 | #define DRV_MODULE_RELDATE "February 18, 2008" | 37 | #define DRV_MODULE_RELDATE "April 24, 2008" |
| 38 | 38 | ||
| 39 | static char version[] __devinitdata = | 39 | static char version[] __devinitdata = |
| 40 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | 40 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; |
| @@ -673,11 +673,16 @@ static int serdes_init_10g(struct niu *np) | |||
| 673 | } | 673 | } |
| 674 | 674 | ||
| 675 | if ((sig & mask) != val) { | 675 | if ((sig & mask) != val) { |
| 676 | if (np->flags & NIU_FLAGS_HOTPLUG_PHY) { | ||
| 677 | np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT; | ||
| 678 | return 0; | ||
| 679 | } | ||
| 676 | dev_err(np->device, PFX "Port %u signal bits [%08x] are not " | 680 | dev_err(np->device, PFX "Port %u signal bits [%08x] are not " |
| 677 | "[%08x]\n", np->port, (int) (sig & mask), (int) val); | 681 | "[%08x]\n", np->port, (int) (sig & mask), (int) val); |
| 678 | return -ENODEV; | 682 | return -ENODEV; |
| 679 | } | 683 | } |
| 680 | 684 | if (np->flags & NIU_FLAGS_HOTPLUG_PHY) | |
| 685 | np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT; | ||
| 681 | return 0; | 686 | return 0; |
| 682 | } | 687 | } |
| 683 | 688 | ||
| @@ -998,6 +1003,28 @@ static int bcm8704_user_dev3_readback(struct niu *np, int reg) | |||
| 998 | return 0; | 1003 | return 0; |
| 999 | } | 1004 | } |
| 1000 | 1005 | ||
| 1006 | static int bcm8706_init_user_dev3(struct niu *np) | ||
| 1007 | { | ||
| 1008 | int err; | ||
| 1009 | |||
| 1010 | |||
| 1011 | err = mdio_read(np, np->phy_addr, BCM8704_USER_DEV3_ADDR, | ||
| 1012 | BCM8704_USER_OPT_DIGITAL_CTRL); | ||
| 1013 | if (err < 0) | ||
| 1014 | return err; | ||
| 1015 | err &= ~USER_ODIG_CTRL_GPIOS; | ||
| 1016 | err |= (0x3 << USER_ODIG_CTRL_GPIOS_SHIFT); | ||
| 1017 | err |= USER_ODIG_CTRL_RESV2; | ||
| 1018 | err = mdio_write(np, np->phy_addr, BCM8704_USER_DEV3_ADDR, | ||
| 1019 | BCM8704_USER_OPT_DIGITAL_CTRL, err); | ||
| 1020 | if (err) | ||
| 1021 | return err; | ||
| 1022 | |||
| 1023 | mdelay(1000); | ||
| 1024 | |||
| 1025 | return 0; | ||
| 1026 | } | ||
| 1027 | |||
| 1001 | static int bcm8704_init_user_dev3(struct niu *np) | 1028 | static int bcm8704_init_user_dev3(struct niu *np) |
| 1002 | { | 1029 | { |
| 1003 | int err; | 1030 | int err; |
| @@ -1127,33 +1154,11 @@ static int xcvr_init_10g_mrvl88x2011(struct niu *np) | |||
| 1127 | MRVL88X2011_10G_PMD_TX_DIS, MRVL88X2011_ENA_PMDTX); | 1154 | MRVL88X2011_10G_PMD_TX_DIS, MRVL88X2011_ENA_PMDTX); |
| 1128 | } | 1155 | } |
| 1129 | 1156 | ||
| 1130 | static int xcvr_init_10g_bcm8704(struct niu *np) | 1157 | |
| 1158 | static int xcvr_diag_bcm870x(struct niu *np) | ||
| 1131 | { | 1159 | { |
| 1132 | struct niu_link_config *lp = &np->link_config; | ||
| 1133 | u16 analog_stat0, tx_alarm_status; | 1160 | u16 analog_stat0, tx_alarm_status; |
| 1134 | int err; | 1161 | int err = 0; |
| 1135 | |||
| 1136 | err = bcm8704_reset(np); | ||
| 1137 | if (err) | ||
| 1138 | return err; | ||
| 1139 | |||
| 1140 | err = bcm8704_init_user_dev3(np); | ||
| 1141 | if (err) | ||
| 1142 | return err; | ||
| 1143 | |||
| 1144 | err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR, | ||
| 1145 | MII_BMCR); | ||
| 1146 | if (err < 0) | ||
| 1147 | return err; | ||
| 1148 | err &= ~BMCR_LOOPBACK; | ||
| 1149 | |||
| 1150 | if (lp->loopback_mode == LOOPBACK_MAC) | ||
| 1151 | err |= BMCR_LOOPBACK; | ||
| 1152 | |||
| 1153 | err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR, | ||
| 1154 | MII_BMCR, err); | ||
| 1155 | if (err) | ||
| 1156 | return err; | ||
| 1157 | 1162 | ||
| 1158 | #if 1 | 1163 | #if 1 |
| 1159 | err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR, | 1164 | err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR, |
| @@ -1211,6 +1216,89 @@ static int xcvr_init_10g_bcm8704(struct niu *np) | |||
| 1211 | return 0; | 1216 | return 0; |
| 1212 | } | 1217 | } |
| 1213 | 1218 | ||
| 1219 | static int xcvr_10g_set_lb_bcm870x(struct niu *np) | ||
| 1220 | { | ||
| 1221 | struct niu_link_config *lp = &np->link_config; | ||
| 1222 | int err; | ||
| 1223 | |||
| 1224 | err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR, | ||
| 1225 | MII_BMCR); | ||
| 1226 | if (err < 0) | ||
| 1227 | return err; | ||
| 1228 | |||
| 1229 | err &= ~BMCR_LOOPBACK; | ||
| 1230 | |||
| 1231 | if (lp->loopback_mode == LOOPBACK_MAC) | ||
| 1232 | err |= BMCR_LOOPBACK; | ||
| 1233 | |||
| 1234 | err = mdio_write(np, np->phy_addr, BCM8704_PCS_DEV_ADDR, | ||
| 1235 | MII_BMCR, err); | ||
| 1236 | if (err) | ||
| 1237 | return err; | ||
| 1238 | |||
| 1239 | return 0; | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | static int xcvr_init_10g_bcm8706(struct niu *np) | ||
| 1243 | { | ||
| 1244 | int err = 0; | ||
| 1245 | u64 val; | ||
| 1246 | |||
| 1247 | if ((np->flags & NIU_FLAGS_HOTPLUG_PHY) && | ||
| 1248 | (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) == 0) | ||
| 1249 | return err; | ||
| 1250 | |||
| 1251 | val = nr64_mac(XMAC_CONFIG); | ||
| 1252 | val &= ~XMAC_CONFIG_LED_POLARITY; | ||
| 1253 | val |= XMAC_CONFIG_FORCE_LED_ON; | ||
| 1254 | nw64_mac(XMAC_CONFIG, val); | ||
| 1255 | |||
| 1256 | val = nr64(MIF_CONFIG); | ||
| 1257 | val |= MIF_CONFIG_INDIRECT_MODE; | ||
| 1258 | nw64(MIF_CONFIG, val); | ||
| 1259 | |||
| 1260 | err = bcm8704_reset(np); | ||
| 1261 | if (err) | ||
| 1262 | return err; | ||
| 1263 | |||
| 1264 | err = xcvr_10g_set_lb_bcm870x(np); | ||
| 1265 | if (err) | ||
| 1266 | return err; | ||
| 1267 | |||
| 1268 | err = bcm8706_init_user_dev3(np); | ||
| 1269 | if (err) | ||
| 1270 | return err; | ||
| 1271 | |||
| 1272 | err = xcvr_diag_bcm870x(np); | ||
| 1273 | if (err) | ||
| 1274 | return err; | ||
| 1275 | |||
| 1276 | return 0; | ||
| 1277 | } | ||
| 1278 | |||
| 1279 | static int xcvr_init_10g_bcm8704(struct niu *np) | ||
| 1280 | { | ||
| 1281 | int err; | ||
| 1282 | |||
| 1283 | err = bcm8704_reset(np); | ||
| 1284 | if (err) | ||
| 1285 | return err; | ||
| 1286 | |||
| 1287 | err = bcm8704_init_user_dev3(np); | ||
| 1288 | if (err) | ||
| 1289 | return err; | ||
| 1290 | |||
| 1291 | err = xcvr_10g_set_lb_bcm870x(np); | ||
| 1292 | if (err) | ||
| 1293 | return err; | ||
| 1294 | |||
| 1295 | err = xcvr_diag_bcm870x(np); | ||
| 1296 | if (err) | ||
| 1297 | return err; | ||
| 1298 | |||
| 1299 | return 0; | ||
| 1300 | } | ||
| 1301 | |||
| 1214 | static int xcvr_init_10g(struct niu *np) | 1302 | static int xcvr_init_10g(struct niu *np) |
| 1215 | { | 1303 | { |
| 1216 | int phy_id, err; | 1304 | int phy_id, err; |
| @@ -1548,6 +1636,59 @@ out: | |||
| 1548 | return err; | 1636 | return err; |
| 1549 | } | 1637 | } |
| 1550 | 1638 | ||
| 1639 | static int link_status_10g_bcm8706(struct niu *np, int *link_up_p) | ||
| 1640 | { | ||
| 1641 | int err, link_up; | ||
| 1642 | link_up = 0; | ||
| 1643 | |||
| 1644 | err = mdio_read(np, np->phy_addr, BCM8704_PMA_PMD_DEV_ADDR, | ||
| 1645 | BCM8704_PMD_RCV_SIGDET); | ||
| 1646 | if (err < 0) | ||
| 1647 | goto out; | ||
| 1648 | if (!(err & PMD_RCV_SIGDET_GLOBAL)) { | ||
| 1649 | err = 0; | ||
| 1650 | goto out; | ||
| 1651 | } | ||
| 1652 | |||
| 1653 | err = mdio_read(np, np->phy_addr, BCM8704_PCS_DEV_ADDR, | ||
| 1654 | BCM8704_PCS_10G_R_STATUS); | ||
| 1655 | if (err < 0) | ||
| 1656 | goto out; | ||
| 1657 | |||
| 1658 | if (!(err & PCS_10G_R_STATUS_BLK_LOCK)) { | ||
| 1659 | err = 0; | ||
| 1660 | goto out; | ||
| 1661 | } | ||
| 1662 | |||
| 1663 | err = mdio_read(np, np->phy_addr, BCM8704_PHYXS_DEV_ADDR, | ||
| 1664 | BCM8704_PHYXS_XGXS_LANE_STAT); | ||
| 1665 | if (err < 0) | ||
| 1666 | goto out; | ||
| 1667 | if (err != (PHYXS_XGXS_LANE_STAT_ALINGED | | ||
| 1668 | PHYXS_XGXS_LANE_STAT_MAGIC | | ||
| 1669 | PHYXS_XGXS_LANE_STAT_PATTEST | | ||
| 1670 | PHYXS_XGXS_LANE_STAT_LANE3 | | ||
| 1671 | PHYXS_XGXS_LANE_STAT_LANE2 | | ||
| 1672 | PHYXS_XGXS_LANE_STAT_LANE1 | | ||
| 1673 | PHYXS_XGXS_LANE_STAT_LANE0)) { | ||
| 1674 | err = 0; | ||
| 1675 | np->link_config.active_speed = SPEED_INVALID; | ||
| 1676 | np->link_config.active_duplex = DUPLEX_INVALID; | ||
| 1677 | goto out; | ||
| 1678 | } | ||
| 1679 | |||
| 1680 | link_up = 1; | ||
| 1681 | np->link_config.active_speed = SPEED_10000; | ||
| 1682 | np->link_config.active_duplex = DUPLEX_FULL; | ||
| 1683 | err = 0; | ||
| 1684 | |||
| 1685 | out: | ||
| 1686 | *link_up_p = link_up; | ||
| 1687 | if (np->flags & NIU_FLAGS_HOTPLUG_PHY) | ||
| 1688 | err = 0; | ||
| 1689 | return err; | ||
| 1690 | } | ||
| 1691 | |||
| 1551 | static int link_status_10g_bcom(struct niu *np, int *link_up_p) | 1692 | static int link_status_10g_bcom(struct niu *np, int *link_up_p) |
| 1552 | { | 1693 | { |
| 1553 | int err, link_up; | 1694 | int err, link_up; |
| @@ -1627,6 +1768,82 @@ static int link_status_10g(struct niu *np, int *link_up_p) | |||
| 1627 | return err; | 1768 | return err; |
| 1628 | } | 1769 | } |
| 1629 | 1770 | ||
| 1771 | static int niu_10g_phy_present(struct niu *np) | ||
| 1772 | { | ||
| 1773 | u64 sig, mask, val; | ||
| 1774 | |||
| 1775 | sig = nr64(ESR_INT_SIGNALS); | ||
| 1776 | switch (np->port) { | ||
| 1777 | case 0: | ||
| 1778 | mask = ESR_INT_SIGNALS_P0_BITS; | ||
| 1779 | val = (ESR_INT_SRDY0_P0 | | ||
| 1780 | ESR_INT_DET0_P0 | | ||
| 1781 | ESR_INT_XSRDY_P0 | | ||
| 1782 | ESR_INT_XDP_P0_CH3 | | ||
| 1783 | ESR_INT_XDP_P0_CH2 | | ||
| 1784 | ESR_INT_XDP_P0_CH1 | | ||
| 1785 | ESR_INT_XDP_P0_CH0); | ||
| 1786 | break; | ||
| 1787 | |||
| 1788 | case 1: | ||
| 1789 | mask = ESR_INT_SIGNALS_P1_BITS; | ||
| 1790 | val = (ESR_INT_SRDY0_P1 | | ||
| 1791 | ESR_INT_DET0_P1 | | ||
| 1792 | ESR_INT_XSRDY_P1 | | ||
| 1793 | ESR_INT_XDP_P1_CH3 | | ||
| 1794 | ESR_INT_XDP_P1_CH2 | | ||
| 1795 | ESR_INT_XDP_P1_CH1 | | ||
| 1796 | ESR_INT_XDP_P1_CH0); | ||
| 1797 | break; | ||
| 1798 | |||
| 1799 | default: | ||
| 1800 | return 0; | ||
| 1801 | } | ||
| 1802 | |||
| 1803 | if ((sig & mask) != val) | ||
| 1804 | return 0; | ||
| 1805 | return 1; | ||
| 1806 | } | ||
| 1807 | |||
| 1808 | static int link_status_10g_hotplug(struct niu *np, int *link_up_p) | ||
| 1809 | { | ||
| 1810 | unsigned long flags; | ||
| 1811 | int err = 0; | ||
| 1812 | int phy_present; | ||
| 1813 | int phy_present_prev; | ||
| 1814 | |||
| 1815 | spin_lock_irqsave(&np->lock, flags); | ||
| 1816 | |||
| 1817 | if (np->link_config.loopback_mode == LOOPBACK_DISABLED) { | ||
| 1818 | phy_present_prev = (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) ? | ||
| 1819 | 1 : 0; | ||
| 1820 | phy_present = niu_10g_phy_present(np); | ||
| 1821 | if (phy_present != phy_present_prev) { | ||
| 1822 | /* state change */ | ||
| 1823 | if (phy_present) { | ||
| 1824 | np->flags |= NIU_FLAGS_HOTPLUG_PHY_PRESENT; | ||
| 1825 | if (np->phy_ops->xcvr_init) | ||
| 1826 | err = np->phy_ops->xcvr_init(np); | ||
| 1827 | if (err) { | ||
| 1828 | /* debounce */ | ||
| 1829 | np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT; | ||
| 1830 | } | ||
| 1831 | } else { | ||
| 1832 | np->flags &= ~NIU_FLAGS_HOTPLUG_PHY_PRESENT; | ||
| 1833 | *link_up_p = 0; | ||
| 1834 | niuwarn(LINK, "%s: Hotplug PHY Removed\n", | ||
| 1835 | np->dev->name); | ||
| 1836 | } | ||
| 1837 | } | ||
| 1838 | if (np->flags & NIU_FLAGS_HOTPLUG_PHY_PRESENT) | ||
| 1839 | err = link_status_10g_bcm8706(np, link_up_p); | ||
| 1840 | } | ||
| 1841 | |||
| 1842 | spin_unlock_irqrestore(&np->lock, flags); | ||
| 1843 | |||
| 1844 | return err; | ||
| 1845 | } | ||
| 1846 | |||
| 1630 | static int link_status_1g(struct niu *np, int *link_up_p) | 1847 | static int link_status_1g(struct niu *np, int *link_up_p) |
| 1631 | { | 1848 | { |
| 1632 | struct niu_link_config *lp = &np->link_config; | 1849 | struct niu_link_config *lp = &np->link_config; |
| @@ -1761,6 +1978,12 @@ static const struct niu_phy_ops phy_ops_10g_fiber = { | |||
| 1761 | .link_status = link_status_10g, | 1978 | .link_status = link_status_10g, |
| 1762 | }; | 1979 | }; |
| 1763 | 1980 | ||
| 1981 | static const struct niu_phy_ops phy_ops_10g_fiber_hotplug = { | ||
| 1982 | .serdes_init = serdes_init_10g, | ||
| 1983 | .xcvr_init = xcvr_init_10g_bcm8706, | ||
| 1984 | .link_status = link_status_10g_hotplug, | ||
| 1985 | }; | ||
| 1986 | |||
| 1764 | static const struct niu_phy_ops phy_ops_10g_copper = { | 1987 | static const struct niu_phy_ops phy_ops_10g_copper = { |
| 1765 | .serdes_init = serdes_init_10g, | 1988 | .serdes_init = serdes_init_10g, |
| 1766 | .link_status = link_status_10g, /* XXX */ | 1989 | .link_status = link_status_10g, /* XXX */ |
| @@ -1792,6 +2015,11 @@ static const struct niu_phy_template phy_template_10g_fiber = { | |||
| 1792 | .phy_addr_base = 8, | 2015 | .phy_addr_base = 8, |
| 1793 | }; | 2016 | }; |
| 1794 | 2017 | ||
| 2018 | static const struct niu_phy_template phy_template_10g_fiber_hotplug = { | ||
| 2019 | .ops = &phy_ops_10g_fiber_hotplug, | ||
| 2020 | .phy_addr_base = 8, | ||
| 2021 | }; | ||
| 2022 | |||
| 1795 | static const struct niu_phy_template phy_template_10g_copper = { | 2023 | static const struct niu_phy_template phy_template_10g_copper = { |
| 1796 | .ops = &phy_ops_10g_copper, | 2024 | .ops = &phy_ops_10g_copper, |
| 1797 | .phy_addr_base = 10, | 2025 | .phy_addr_base = 10, |
| @@ -1996,6 +2224,13 @@ static int niu_determine_phy_disposition(struct niu *np) | |||
| 1996 | plat_type == PLAT_TYPE_VF_P1) | 2224 | plat_type == PLAT_TYPE_VF_P1) |
| 1997 | phy_addr_off = 8; | 2225 | phy_addr_off = 8; |
| 1998 | phy_addr_off += np->port; | 2226 | phy_addr_off += np->port; |
| 2227 | if (np->flags & NIU_FLAGS_HOTPLUG_PHY) { | ||
| 2228 | tp = &phy_template_10g_fiber_hotplug; | ||
| 2229 | if (np->port == 0) | ||
| 2230 | phy_addr_off = 8; | ||
| 2231 | if (np->port == 1) | ||
| 2232 | phy_addr_off = 12; | ||
| 2233 | } | ||
| 1999 | break; | 2234 | break; |
| 2000 | 2235 | ||
| 2001 | case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES: | 2236 | case NIU_FLAGS_10G | NIU_FLAGS_XCVR_SERDES: |
| @@ -6773,6 +7008,37 @@ static int __devinit niu_phy_type_prop_decode(struct niu *np, | |||
| 6773 | return 0; | 7008 | return 0; |
| 6774 | } | 7009 | } |
| 6775 | 7010 | ||
| 7011 | /* niu board models have a trailing dash version incremented | ||
| 7012 | * with HW rev change. Need to ingnore the dash version while | ||
| 7013 | * checking for match | ||
| 7014 | * | ||
| 7015 | * for example, for the 10G card the current vpd.board_model | ||
| 7016 | * is 501-5283-04, of which -04 is the dash version and have | ||
| 7017 | * to be ignored | ||
| 7018 | */ | ||
| 7019 | static int niu_board_model_match(struct niu *np, const char *model) | ||
| 7020 | { | ||
| 7021 | return !strncmp(np->vpd.board_model, model, strlen(model)); | ||
| 7022 | } | ||
| 7023 | |||
| 7024 | static int niu_pci_vpd_get_nports(struct niu *np) | ||
| 7025 | { | ||
| 7026 | int ports = 0; | ||
| 7027 | |||
| 7028 | if ((niu_board_model_match(np, NIU_QGC_LP_BM_STR)) || | ||
| 7029 | (niu_board_model_match(np, NIU_QGC_PEM_BM_STR)) || | ||
| 7030 | (niu_board_model_match(np, NIU_ALONSO_BM_STR))) { | ||
| 7031 | ports = 4; | ||
| 7032 | } else if ((niu_board_model_match(np, NIU_2XGF_LP_BM_STR)) || | ||
| 7033 | (niu_board_model_match(np, NIU_2XGF_PEM_BM_STR)) || | ||
| 7034 | (niu_board_model_match(np, NIU_FOXXY_BM_STR)) || | ||
| 7035 | (niu_board_model_match(np, NIU_2XGF_MRVL_BM_STR))) { | ||
| 7036 | ports = 2; | ||
| 7037 | } | ||
| 7038 | |||
| 7039 | return ports; | ||
| 7040 | } | ||
| 7041 | |||
| 6776 | static void __devinit niu_pci_vpd_validate(struct niu *np) | 7042 | static void __devinit niu_pci_vpd_validate(struct niu *np) |
| 6777 | { | 7043 | { |
| 6778 | struct net_device *dev = np->dev; | 7044 | struct net_device *dev = np->dev; |
| @@ -6799,6 +7065,9 @@ static void __devinit niu_pci_vpd_validate(struct niu *np) | |||
| 6799 | } | 7065 | } |
| 6800 | if (np->flags & NIU_FLAGS_10G) | 7066 | if (np->flags & NIU_FLAGS_10G) |
| 6801 | np->mac_xcvr = MAC_XCVR_XPCS; | 7067 | np->mac_xcvr = MAC_XCVR_XPCS; |
| 7068 | } else if (niu_board_model_match(np, NIU_FOXXY_BM_STR)) { | ||
| 7069 | np->flags |= (NIU_FLAGS_10G | NIU_FLAGS_FIBER | | ||
| 7070 | NIU_FLAGS_HOTPLUG_PHY); | ||
| 6802 | } else if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) { | 7071 | } else if (niu_phy_type_prop_decode(np, np->vpd.phy_type)) { |
| 6803 | dev_err(np->device, PFX "Illegal phy string [%s].\n", | 7072 | dev_err(np->device, PFX "Illegal phy string [%s].\n", |
| 6804 | np->vpd.phy_type); | 7073 | np->vpd.phy_type); |
| @@ -6987,11 +7256,17 @@ static int __devinit niu_get_and_validate_port(struct niu *np) | |||
| 6987 | if (parent->plat_type == PLAT_TYPE_NIU) { | 7256 | if (parent->plat_type == PLAT_TYPE_NIU) { |
| 6988 | parent->num_ports = 2; | 7257 | parent->num_ports = 2; |
| 6989 | } else { | 7258 | } else { |
| 6990 | parent->num_ports = nr64(ESPC_NUM_PORTS_MACS) & | 7259 | parent->num_ports = niu_pci_vpd_get_nports(np); |
| 6991 | ESPC_NUM_PORTS_MACS_VAL; | 7260 | if (!parent->num_ports) { |
| 6992 | 7261 | /* Fall back to SPROM as last resort. | |
| 6993 | if (!parent->num_ports) | 7262 | * This will fail on most cards. |
| 6994 | parent->num_ports = 4; | 7263 | */ |
| 7264 | parent->num_ports = nr64(ESPC_NUM_PORTS_MACS) & | ||
| 7265 | ESPC_NUM_PORTS_MACS_VAL; | ||
| 7266 | |||
| 7267 | if (!parent->num_ports) | ||
| 7268 | return -ENODEV; | ||
| 7269 | } | ||
| 6995 | } | 7270 | } |
| 6996 | } | 7271 | } |
| 6997 | 7272 | ||
| @@ -7015,7 +7290,8 @@ static int __devinit phy_record(struct niu_parent *parent, | |||
| 7015 | return 0; | 7290 | return 0; |
| 7016 | if (type == PHY_TYPE_PMA_PMD || type == PHY_TYPE_PCS) { | 7291 | if (type == PHY_TYPE_PMA_PMD || type == PHY_TYPE_PCS) { |
| 7017 | if (((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8704) && | 7292 | if (((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8704) && |
| 7018 | ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011)) | 7293 | ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_MRVL88X2011) && |
| 7294 | ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM8706)) | ||
| 7019 | return 0; | 7295 | return 0; |
| 7020 | } else { | 7296 | } else { |
| 7021 | if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM5464R) | 7297 | if ((id & NIU_PHY_ID_MASK) != NIU_PHY_ID_BCM5464R) |
| @@ -7262,7 +7538,6 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent) | |||
| 7262 | u32 val; | 7538 | u32 val; |
| 7263 | int err; | 7539 | int err; |
| 7264 | 7540 | ||
| 7265 | |||
| 7266 | if (!strcmp(np->vpd.model, "SUNW,CP3220") || | 7541 | if (!strcmp(np->vpd.model, "SUNW,CP3220") || |
| 7267 | !strcmp(np->vpd.model, "SUNW,CP3260")) { | 7542 | !strcmp(np->vpd.model, "SUNW,CP3260")) { |
| 7268 | num_10g = 0; | 7543 | num_10g = 0; |
| @@ -7273,6 +7548,12 @@ static int __devinit walk_phys(struct niu *np, struct niu_parent *parent) | |||
| 7273 | phy_encode(PORT_TYPE_1G, 1) | | 7548 | phy_encode(PORT_TYPE_1G, 1) | |
| 7274 | phy_encode(PORT_TYPE_1G, 2) | | 7549 | phy_encode(PORT_TYPE_1G, 2) | |
| 7275 | phy_encode(PORT_TYPE_1G, 3)); | 7550 | phy_encode(PORT_TYPE_1G, 3)); |
| 7551 | } else if (niu_board_model_match(np, NIU_FOXXY_BM_STR)) { | ||
| 7552 | num_10g = 2; | ||
| 7553 | num_1g = 0; | ||
| 7554 | parent->num_ports = 2; | ||
| 7555 | val = (phy_encode(PORT_TYPE_10G, 0) | | ||
| 7556 | phy_encode(PORT_TYPE_10G, 1)); | ||
| 7276 | } else { | 7557 | } else { |
| 7277 | err = fill_phy_probe_info(np, parent, info); | 7558 | err = fill_phy_probe_info(np, parent, info); |
| 7278 | if (err) | 7559 | if (err) |
| @@ -7733,15 +8014,16 @@ static int __devinit niu_get_invariants(struct niu *np) | |||
| 7733 | 8014 | ||
| 7734 | have_props = !err; | 8015 | have_props = !err; |
| 7735 | 8016 | ||
| 7736 | err = niu_get_and_validate_port(np); | ||
| 7737 | if (err) | ||
| 7738 | return err; | ||
| 7739 | |||
| 7740 | err = niu_init_mac_ipp_pcs_base(np); | 8017 | err = niu_init_mac_ipp_pcs_base(np); |
| 7741 | if (err) | 8018 | if (err) |
| 7742 | return err; | 8019 | return err; |
| 7743 | 8020 | ||
| 7744 | if (!have_props) { | 8021 | if (have_props) { |
| 8022 | err = niu_get_and_validate_port(np); | ||
| 8023 | if (err) | ||
| 8024 | return err; | ||
| 8025 | |||
| 8026 | } else { | ||
| 7745 | if (np->parent->plat_type == PLAT_TYPE_NIU) | 8027 | if (np->parent->plat_type == PLAT_TYPE_NIU) |
| 7746 | return -EINVAL; | 8028 | return -EINVAL; |
| 7747 | 8029 | ||
| @@ -7753,10 +8035,17 @@ static int __devinit niu_get_invariants(struct niu *np) | |||
| 7753 | niu_pci_vpd_fetch(np, offset); | 8035 | niu_pci_vpd_fetch(np, offset); |
| 7754 | nw64(ESPC_PIO_EN, 0); | 8036 | nw64(ESPC_PIO_EN, 0); |
| 7755 | 8037 | ||
| 7756 | if (np->flags & NIU_FLAGS_VPD_VALID) | 8038 | if (np->flags & NIU_FLAGS_VPD_VALID) { |
| 7757 | niu_pci_vpd_validate(np); | 8039 | niu_pci_vpd_validate(np); |
| 8040 | err = niu_get_and_validate_port(np); | ||
| 8041 | if (err) | ||
| 8042 | return err; | ||
| 8043 | } | ||
| 7758 | 8044 | ||
| 7759 | if (!(np->flags & NIU_FLAGS_VPD_VALID)) { | 8045 | if (!(np->flags & NIU_FLAGS_VPD_VALID)) { |
| 8046 | err = niu_get_and_validate_port(np); | ||
| 8047 | if (err) | ||
| 8048 | return err; | ||
| 7760 | err = niu_pci_probe_sprom(np); | 8049 | err = niu_pci_probe_sprom(np); |
| 7761 | if (err) | 8050 | if (err) |
| 7762 | return err; | 8051 | return err; |
diff --git a/drivers/net/niu.h b/drivers/net/niu.h index 336aed08b275..97ffbe137bcb 100644 --- a/drivers/net/niu.h +++ b/drivers/net/niu.h | |||
| @@ -2537,6 +2537,7 @@ struct fcram_hash_ipv6 { | |||
| 2537 | 2537 | ||
| 2538 | #define NIU_PHY_ID_MASK 0xfffff0f0 | 2538 | #define NIU_PHY_ID_MASK 0xfffff0f0 |
| 2539 | #define NIU_PHY_ID_BCM8704 0x00206030 | 2539 | #define NIU_PHY_ID_BCM8704 0x00206030 |
| 2540 | #define NIU_PHY_ID_BCM8706 0x00206035 | ||
| 2540 | #define NIU_PHY_ID_BCM5464R 0x002060b0 | 2541 | #define NIU_PHY_ID_BCM5464R 0x002060b0 |
| 2541 | #define NIU_PHY_ID_MRVL88X2011 0x01410020 | 2542 | #define NIU_PHY_ID_MRVL88X2011 0x01410020 |
| 2542 | 2543 | ||
| @@ -2937,6 +2938,15 @@ struct rx_ring_info { | |||
| 2937 | 2938 | ||
| 2938 | #define NIU_MAX_MTU 9216 | 2939 | #define NIU_MAX_MTU 9216 |
| 2939 | 2940 | ||
| 2941 | /* VPD strings */ | ||
| 2942 | #define NIU_QGC_LP_BM_STR "501-7606" | ||
| 2943 | #define NIU_2XGF_LP_BM_STR "501-7283" | ||
| 2944 | #define NIU_QGC_PEM_BM_STR "501-7765" | ||
| 2945 | #define NIU_2XGF_PEM_BM_STR "501-7626" | ||
| 2946 | #define NIU_ALONSO_BM_STR "373-0202" | ||
| 2947 | #define NIU_FOXXY_BM_STR "501-7961" | ||
| 2948 | #define NIU_2XGF_MRVL_BM_STR "SK-6E82" | ||
| 2949 | |||
| 2940 | #define NIU_VPD_MIN_MAJOR 3 | 2950 | #define NIU_VPD_MIN_MAJOR 3 |
| 2941 | #define NIU_VPD_MIN_MINOR 4 | 2951 | #define NIU_VPD_MIN_MINOR 4 |
| 2942 | 2952 | ||
| @@ -3199,6 +3209,8 @@ struct niu { | |||
| 3199 | struct niu_parent *parent; | 3209 | struct niu_parent *parent; |
| 3200 | 3210 | ||
| 3201 | u32 flags; | 3211 | u32 flags; |
| 3212 | #define NIU_FLAGS_HOTPLUG_PHY_PRESENT 0x02000000 /* Removebale PHY detected*/ | ||
| 3213 | #define NIU_FLAGS_HOTPLUG_PHY 0x01000000 /* Removebale PHY */ | ||
| 3202 | #define NIU_FLAGS_VPD_VALID 0x00800000 /* VPD has valid version */ | 3214 | #define NIU_FLAGS_VPD_VALID 0x00800000 /* VPD has valid version */ |
| 3203 | #define NIU_FLAGS_MSIX 0x00400000 /* MSI-X in use */ | 3215 | #define NIU_FLAGS_MSIX 0x00400000 /* MSI-X in use */ |
| 3204 | #define NIU_FLAGS_MCAST 0x00200000 /* multicast filter enabled */ | 3216 | #define NIU_FLAGS_MCAST 0x00200000 /* multicast filter enabled */ |
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 963630c65ca9..94e0b7ed76f1 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c | |||
| @@ -89,6 +89,9 @@ int mdiobus_register(struct mii_bus *bus) | |||
| 89 | 89 | ||
| 90 | phydev->bus = bus; | 90 | phydev->bus = bus; |
| 91 | 91 | ||
| 92 | /* Run all of the fixups for this PHY */ | ||
| 93 | phy_scan_fixups(phydev); | ||
| 94 | |||
| 92 | err = device_register(&phydev->dev); | 95 | err = device_register(&phydev->dev); |
| 93 | 96 | ||
| 94 | if (err) { | 97 | if (err) { |
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 12fccb1c76dc..3c18bb594957 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c | |||
| @@ -406,8 +406,10 @@ int phy_mii_ioctl(struct phy_device *phydev, | |||
| 406 | 406 | ||
| 407 | if (mii_data->reg_num == MII_BMCR | 407 | if (mii_data->reg_num == MII_BMCR |
| 408 | && val & BMCR_RESET | 408 | && val & BMCR_RESET |
| 409 | && phydev->drv->config_init) | 409 | && phydev->drv->config_init) { |
| 410 | phy_scan_fixups(phydev); | ||
| 410 | phydev->drv->config_init(phydev); | 411 | phydev->drv->config_init(phydev); |
| 412 | } | ||
| 411 | break; | 413 | break; |
| 412 | 414 | ||
| 413 | default: | 415 | default: |
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 8b1121b02f98..ddf8d51832a6 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
| @@ -53,6 +53,96 @@ static void phy_device_release(struct device *dev) | |||
| 53 | phy_device_free(to_phy_device(dev)); | 53 | phy_device_free(to_phy_device(dev)); |
| 54 | } | 54 | } |
| 55 | 55 | ||
| 56 | static LIST_HEAD(phy_fixup_list); | ||
| 57 | static DEFINE_MUTEX(phy_fixup_lock); | ||
| 58 | |||
| 59 | /* | ||
| 60 | * Creates a new phy_fixup and adds it to the list | ||
| 61 | * @bus_id: A string which matches phydev->dev.bus_id (or PHY_ANY_ID) | ||
| 62 | * @phy_uid: Used to match against phydev->phy_id (the UID of the PHY) | ||
| 63 | * It can also be PHY_ANY_UID | ||
| 64 | * @phy_uid_mask: Applied to phydev->phy_id and fixup->phy_uid before | ||
| 65 | * comparison | ||
| 66 | * @run: The actual code to be run when a matching PHY is found | ||
| 67 | */ | ||
| 68 | int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask, | ||
| 69 | int (*run)(struct phy_device *)) | ||
| 70 | { | ||
| 71 | struct phy_fixup *fixup; | ||
| 72 | |||
| 73 | fixup = kzalloc(sizeof(struct phy_fixup), GFP_KERNEL); | ||
| 74 | if (!fixup) | ||
| 75 | return -ENOMEM; | ||
| 76 | |||
| 77 | strncpy(fixup->bus_id, bus_id, BUS_ID_SIZE); | ||
| 78 | fixup->phy_uid = phy_uid; | ||
| 79 | fixup->phy_uid_mask = phy_uid_mask; | ||
| 80 | fixup->run = run; | ||
| 81 | |||
| 82 | mutex_lock(&phy_fixup_lock); | ||
| 83 | list_add_tail(&fixup->list, &phy_fixup_list); | ||
| 84 | mutex_unlock(&phy_fixup_lock); | ||
| 85 | |||
| 86 | return 0; | ||
| 87 | } | ||
| 88 | EXPORT_SYMBOL(phy_register_fixup); | ||
| 89 | |||
| 90 | /* Registers a fixup to be run on any PHY with the UID in phy_uid */ | ||
| 91 | int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask, | ||
| 92 | int (*run)(struct phy_device *)) | ||
| 93 | { | ||
| 94 | return phy_register_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask, run); | ||
| 95 | } | ||
| 96 | EXPORT_SYMBOL(phy_register_fixup_for_uid); | ||
| 97 | |||
| 98 | /* Registers a fixup to be run on the PHY with id string bus_id */ | ||
| 99 | int phy_register_fixup_for_id(const char *bus_id, | ||
| 100 | int (*run)(struct phy_device *)) | ||
| 101 | { | ||
| 102 | return phy_register_fixup(bus_id, PHY_ANY_UID, 0xffffffff, run); | ||
| 103 | } | ||
| 104 | EXPORT_SYMBOL(phy_register_fixup_for_id); | ||
| 105 | |||
| 106 | /* | ||
| 107 | * Returns 1 if fixup matches phydev in bus_id and phy_uid. | ||
| 108 | * Fixups can be set to match any in one or more fields. | ||
| 109 | */ | ||
| 110 | static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup) | ||
| 111 | { | ||
| 112 | if (strcmp(fixup->bus_id, phydev->dev.bus_id) != 0) | ||
| 113 | if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0) | ||
| 114 | return 0; | ||
| 115 | |||
| 116 | if ((fixup->phy_uid & fixup->phy_uid_mask) != | ||
| 117 | (phydev->phy_id & fixup->phy_uid_mask)) | ||
| 118 | if (fixup->phy_uid != PHY_ANY_UID) | ||
| 119 | return 0; | ||
| 120 | |||
| 121 | return 1; | ||
| 122 | } | ||
| 123 | |||
| 124 | /* Runs any matching fixups for this phydev */ | ||
| 125 | int phy_scan_fixups(struct phy_device *phydev) | ||
| 126 | { | ||
| 127 | struct phy_fixup *fixup; | ||
| 128 | |||
| 129 | mutex_lock(&phy_fixup_lock); | ||
| 130 | list_for_each_entry(fixup, &phy_fixup_list, list) { | ||
| 131 | if (phy_needs_fixup(phydev, fixup)) { | ||
| 132 | int err; | ||
| 133 | |||
| 134 | err = fixup->run(phydev); | ||
| 135 | |||
| 136 | if (err < 0) | ||
| 137 | return err; | ||
| 138 | } | ||
| 139 | } | ||
| 140 | mutex_unlock(&phy_fixup_lock); | ||
| 141 | |||
| 142 | return 0; | ||
| 143 | } | ||
| 144 | EXPORT_SYMBOL(phy_scan_fixups); | ||
| 145 | |||
| 56 | struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) | 146 | struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) |
| 57 | { | 147 | { |
| 58 | struct phy_device *dev; | 148 | struct phy_device *dev; |
| @@ -179,13 +269,13 @@ void phy_prepare_link(struct phy_device *phydev, | |||
| 179 | * choose to call only the subset of functions which provide | 269 | * choose to call only the subset of functions which provide |
| 180 | * the desired functionality. | 270 | * the desired functionality. |
| 181 | */ | 271 | */ |
| 182 | struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, | 272 | struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, |
| 183 | void (*handler)(struct net_device *), u32 flags, | 273 | void (*handler)(struct net_device *), u32 flags, |
| 184 | phy_interface_t interface) | 274 | phy_interface_t interface) |
| 185 | { | 275 | { |
| 186 | struct phy_device *phydev; | 276 | struct phy_device *phydev; |
| 187 | 277 | ||
| 188 | phydev = phy_attach(dev, phy_id, flags, interface); | 278 | phydev = phy_attach(dev, bus_id, flags, interface); |
| 189 | 279 | ||
| 190 | if (IS_ERR(phydev)) | 280 | if (IS_ERR(phydev)) |
| 191 | return phydev; | 281 | return phydev; |
| @@ -226,7 +316,7 @@ static int phy_compare_id(struct device *dev, void *data) | |||
| 226 | /** | 316 | /** |
| 227 | * phy_attach - attach a network device to a particular PHY device | 317 | * phy_attach - attach a network device to a particular PHY device |
| 228 | * @dev: network device to attach | 318 | * @dev: network device to attach |
| 229 | * @phy_id: PHY device to attach | 319 | * @bus_id: PHY device to attach |
| 230 | * @flags: PHY device's dev_flags | 320 | * @flags: PHY device's dev_flags |
| 231 | * @interface: PHY device's interface | 321 | * @interface: PHY device's interface |
| 232 | * | 322 | * |
| @@ -238,7 +328,7 @@ static int phy_compare_id(struct device *dev, void *data) | |||
| 238 | * change. The phy_device is returned to the attaching driver. | 328 | * change. The phy_device is returned to the attaching driver. |
| 239 | */ | 329 | */ |
| 240 | struct phy_device *phy_attach(struct net_device *dev, | 330 | struct phy_device *phy_attach(struct net_device *dev, |
| 241 | const char *phy_id, u32 flags, phy_interface_t interface) | 331 | const char *bus_id, u32 flags, phy_interface_t interface) |
| 242 | { | 332 | { |
| 243 | struct bus_type *bus = &mdio_bus_type; | 333 | struct bus_type *bus = &mdio_bus_type; |
| 244 | struct phy_device *phydev; | 334 | struct phy_device *phydev; |
| @@ -246,12 +336,12 @@ struct phy_device *phy_attach(struct net_device *dev, | |||
| 246 | 336 | ||
| 247 | /* Search the list of PHY devices on the mdio bus for the | 337 | /* Search the list of PHY devices on the mdio bus for the |
| 248 | * PHY with the requested name */ | 338 | * PHY with the requested name */ |
| 249 | d = bus_find_device(bus, NULL, (void *)phy_id, phy_compare_id); | 339 | d = bus_find_device(bus, NULL, (void *)bus_id, phy_compare_id); |
| 250 | 340 | ||
| 251 | if (d) { | 341 | if (d) { |
| 252 | phydev = to_phy_device(d); | 342 | phydev = to_phy_device(d); |
| 253 | } else { | 343 | } else { |
| 254 | printk(KERN_ERR "%s not found\n", phy_id); | 344 | printk(KERN_ERR "%s not found\n", bus_id); |
| 255 | return ERR_PTR(-ENODEV); | 345 | return ERR_PTR(-ENODEV); |
| 256 | } | 346 | } |
| 257 | 347 | ||
| @@ -271,7 +361,7 @@ struct phy_device *phy_attach(struct net_device *dev, | |||
| 271 | 361 | ||
| 272 | if (phydev->attached_dev) { | 362 | if (phydev->attached_dev) { |
| 273 | printk(KERN_ERR "%s: %s already attached\n", | 363 | printk(KERN_ERR "%s: %s already attached\n", |
| 274 | dev->name, phy_id); | 364 | dev->name, bus_id); |
| 275 | return ERR_PTR(-EBUSY); | 365 | return ERR_PTR(-EBUSY); |
| 276 | } | 366 | } |
| 277 | 367 | ||
| @@ -287,6 +377,11 @@ struct phy_device *phy_attach(struct net_device *dev, | |||
| 287 | if (phydev->drv->config_init) { | 377 | if (phydev->drv->config_init) { |
| 288 | int err; | 378 | int err; |
| 289 | 379 | ||
| 380 | err = phy_scan_fixups(phydev); | ||
| 381 | |||
| 382 | if (err < 0) | ||
| 383 | return ERR_PTR(err); | ||
| 384 | |||
| 290 | err = phydev->drv->config_init(phydev); | 385 | err = phydev->drv->config_init(phydev); |
| 291 | 386 | ||
| 292 | if (err < 0) | 387 | if (err < 0) |
| @@ -395,6 +490,7 @@ EXPORT_SYMBOL(genphy_config_advert); | |||
| 395 | */ | 490 | */ |
| 396 | int genphy_setup_forced(struct phy_device *phydev) | 491 | int genphy_setup_forced(struct phy_device *phydev) |
| 397 | { | 492 | { |
| 493 | int err; | ||
| 398 | int ctl = 0; | 494 | int ctl = 0; |
| 399 | 495 | ||
| 400 | phydev->pause = phydev->asym_pause = 0; | 496 | phydev->pause = phydev->asym_pause = 0; |
| @@ -407,17 +503,26 @@ int genphy_setup_forced(struct phy_device *phydev) | |||
| 407 | if (DUPLEX_FULL == phydev->duplex) | 503 | if (DUPLEX_FULL == phydev->duplex) |
| 408 | ctl |= BMCR_FULLDPLX; | 504 | ctl |= BMCR_FULLDPLX; |
| 409 | 505 | ||
| 410 | ctl = phy_write(phydev, MII_BMCR, ctl); | 506 | err = phy_write(phydev, MII_BMCR, ctl); |
| 411 | 507 | ||
| 412 | if (ctl < 0) | 508 | if (err < 0) |
| 413 | return ctl; | 509 | return err; |
| 510 | |||
| 511 | /* | ||
| 512 | * Run the fixups on this PHY, just in case the | ||
| 513 | * board code needs to change something after a reset | ||
| 514 | */ | ||
| 515 | err = phy_scan_fixups(phydev); | ||
| 516 | |||
| 517 | if (err < 0) | ||
| 518 | return err; | ||
| 414 | 519 | ||
| 415 | /* We just reset the device, so we'd better configure any | 520 | /* We just reset the device, so we'd better configure any |
| 416 | * settings the PHY requires to operate */ | 521 | * settings the PHY requires to operate */ |
| 417 | if (phydev->drv->config_init) | 522 | if (phydev->drv->config_init) |
| 418 | ctl = phydev->drv->config_init(phydev); | 523 | err = phydev->drv->config_init(phydev); |
| 419 | 524 | ||
| 420 | return ctl; | 525 | return err; |
| 421 | } | 526 | } |
| 422 | 527 | ||
| 423 | 528 | ||
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index dcbe01b0ca0d..157fd932e951 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c | |||
| @@ -86,7 +86,7 @@ | |||
| 86 | #include "s2io.h" | 86 | #include "s2io.h" |
| 87 | #include "s2io-regs.h" | 87 | #include "s2io-regs.h" |
| 88 | 88 | ||
| 89 | #define DRV_VERSION "2.0.26.20" | 89 | #define DRV_VERSION "2.0.26.22" |
| 90 | 90 | ||
| 91 | /* S2io Driver name & version. */ | 91 | /* S2io Driver name & version. */ |
| 92 | static char s2io_driver_name[] = "Neterion"; | 92 | static char s2io_driver_name[] = "Neterion"; |
| @@ -117,20 +117,6 @@ static inline int RXD_IS_UP2DT(struct RxD_t *rxdp) | |||
| 117 | 117 | ||
| 118 | #define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \ | 118 | #define LINK_IS_UP(val64) (!(val64 & (ADAPTER_STATUS_RMAC_REMOTE_FAULT | \ |
| 119 | ADAPTER_STATUS_RMAC_LOCAL_FAULT))) | 119 | ADAPTER_STATUS_RMAC_LOCAL_FAULT))) |
| 120 | #define TASKLET_IN_USE test_and_set_bit(0, (&sp->tasklet_status)) | ||
| 121 | #define PANIC 1 | ||
| 122 | #define LOW 2 | ||
| 123 | static inline int rx_buffer_level(struct s2io_nic * sp, int rxb_size, int ring) | ||
| 124 | { | ||
| 125 | struct mac_info *mac_control; | ||
| 126 | |||
| 127 | mac_control = &sp->mac_control; | ||
| 128 | if (rxb_size <= rxd_count[sp->rxd_mode]) | ||
| 129 | return PANIC; | ||
| 130 | else if ((mac_control->rings[ring].pkt_cnt - rxb_size) > 16) | ||
| 131 | return LOW; | ||
| 132 | return 0; | ||
| 133 | } | ||
| 134 | 120 | ||
| 135 | static inline int is_s2io_card_up(const struct s2io_nic * sp) | 121 | static inline int is_s2io_card_up(const struct s2io_nic * sp) |
| 136 | { | 122 | { |
| @@ -2458,7 +2444,7 @@ static void free_tx_buffers(struct s2io_nic *nic) | |||
| 2458 | for (i = 0; i < config->tx_fifo_num; i++) { | 2444 | for (i = 0; i < config->tx_fifo_num; i++) { |
| 2459 | unsigned long flags; | 2445 | unsigned long flags; |
| 2460 | spin_lock_irqsave(&mac_control->fifos[i].tx_lock, flags); | 2446 | spin_lock_irqsave(&mac_control->fifos[i].tx_lock, flags); |
| 2461 | for (j = 0; j < config->tx_cfg[i].fifo_len - 1; j++) { | 2447 | for (j = 0; j < config->tx_cfg[i].fifo_len; j++) { |
| 2462 | txdp = (struct TxD *) \ | 2448 | txdp = (struct TxD *) \ |
| 2463 | mac_control->fifos[i].list_info[j].list_virt_addr; | 2449 | mac_control->fifos[i].list_info[j].list_virt_addr; |
| 2464 | skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j); | 2450 | skb = s2io_txdl_getskb(&mac_control->fifos[i], txdp, j); |
| @@ -2544,7 +2530,6 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) | |||
| 2544 | struct config_param *config; | 2530 | struct config_param *config; |
| 2545 | u64 tmp; | 2531 | u64 tmp; |
| 2546 | struct buffAdd *ba; | 2532 | struct buffAdd *ba; |
| 2547 | unsigned long flags; | ||
| 2548 | struct RxD_t *first_rxdp = NULL; | 2533 | struct RxD_t *first_rxdp = NULL; |
| 2549 | u64 Buffer0_ptr = 0, Buffer1_ptr = 0; | 2534 | u64 Buffer0_ptr = 0, Buffer1_ptr = 0; |
| 2550 | struct RxD1 *rxdp1; | 2535 | struct RxD1 *rxdp1; |
| @@ -2592,15 +2577,7 @@ static int fill_rx_buffers(struct s2io_nic *nic, int ring_no) | |||
| 2592 | DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n", | 2577 | DBG_PRINT(INTR_DBG, "%s: Next block at: %p\n", |
| 2593 | dev->name, rxdp); | 2578 | dev->name, rxdp); |
| 2594 | } | 2579 | } |
| 2595 | if(!napi) { | 2580 | |
| 2596 | spin_lock_irqsave(&nic->put_lock, flags); | ||
| 2597 | mac_control->rings[ring_no].put_pos = | ||
| 2598 | (block_no * (rxd_count[nic->rxd_mode] + 1)) + off; | ||
| 2599 | spin_unlock_irqrestore(&nic->put_lock, flags); | ||
| 2600 | } else { | ||
| 2601 | mac_control->rings[ring_no].put_pos = | ||
| 2602 | (block_no * (rxd_count[nic->rxd_mode] + 1)) + off; | ||
| 2603 | } | ||
| 2604 | if ((rxdp->Control_1 & RXD_OWN_XENA) && | 2581 | if ((rxdp->Control_1 & RXD_OWN_XENA) && |
| 2605 | ((nic->rxd_mode == RXD_MODE_3B) && | 2582 | ((nic->rxd_mode == RXD_MODE_3B) && |
| 2606 | (rxdp->Control_2 & s2BIT(0)))) { | 2583 | (rxdp->Control_2 & s2BIT(0)))) { |
| @@ -2978,7 +2955,7 @@ static void rx_intr_handler(struct ring_info *ring_data) | |||
| 2978 | { | 2955 | { |
| 2979 | struct s2io_nic *nic = ring_data->nic; | 2956 | struct s2io_nic *nic = ring_data->nic; |
| 2980 | struct net_device *dev = (struct net_device *) nic->dev; | 2957 | struct net_device *dev = (struct net_device *) nic->dev; |
| 2981 | int get_block, put_block, put_offset; | 2958 | int get_block, put_block; |
| 2982 | struct rx_curr_get_info get_info, put_info; | 2959 | struct rx_curr_get_info get_info, put_info; |
| 2983 | struct RxD_t *rxdp; | 2960 | struct RxD_t *rxdp; |
| 2984 | struct sk_buff *skb; | 2961 | struct sk_buff *skb; |
| @@ -2987,19 +2964,11 @@ static void rx_intr_handler(struct ring_info *ring_data) | |||
| 2987 | struct RxD1* rxdp1; | 2964 | struct RxD1* rxdp1; |
| 2988 | struct RxD3* rxdp3; | 2965 | struct RxD3* rxdp3; |
| 2989 | 2966 | ||
| 2990 | spin_lock(&nic->rx_lock); | ||
| 2991 | |||
| 2992 | get_info = ring_data->rx_curr_get_info; | 2967 | get_info = ring_data->rx_curr_get_info; |
| 2993 | get_block = get_info.block_index; | 2968 | get_block = get_info.block_index; |
| 2994 | memcpy(&put_info, &ring_data->rx_curr_put_info, sizeof(put_info)); | 2969 | memcpy(&put_info, &ring_data->rx_curr_put_info, sizeof(put_info)); |
| 2995 | put_block = put_info.block_index; | 2970 | put_block = put_info.block_index; |
| 2996 | rxdp = ring_data->rx_blocks[get_block].rxds[get_info.offset].virt_addr; | 2971 | rxdp = ring_data->rx_blocks[get_block].rxds[get_info.offset].virt_addr; |
| 2997 | if (!napi) { | ||
| 2998 | spin_lock(&nic->put_lock); | ||
| 2999 | put_offset = ring_data->put_pos; | ||
| 3000 | spin_unlock(&nic->put_lock); | ||
| 3001 | } else | ||
| 3002 | put_offset = ring_data->put_pos; | ||
| 3003 | 2972 | ||
| 3004 | while (RXD_IS_UP2DT(rxdp)) { | 2973 | while (RXD_IS_UP2DT(rxdp)) { |
| 3005 | /* | 2974 | /* |
| @@ -3016,7 +2985,6 @@ static void rx_intr_handler(struct ring_info *ring_data) | |||
| 3016 | DBG_PRINT(ERR_DBG, "%s: The skb is ", | 2985 | DBG_PRINT(ERR_DBG, "%s: The skb is ", |
| 3017 | dev->name); | 2986 | dev->name); |
| 3018 | DBG_PRINT(ERR_DBG, "Null in Rx Intr\n"); | 2987 | DBG_PRINT(ERR_DBG, "Null in Rx Intr\n"); |
| 3019 | spin_unlock(&nic->rx_lock); | ||
| 3020 | return; | 2988 | return; |
| 3021 | } | 2989 | } |
| 3022 | if (nic->rxd_mode == RXD_MODE_1) { | 2990 | if (nic->rxd_mode == RXD_MODE_1) { |
| @@ -3072,8 +3040,6 @@ static void rx_intr_handler(struct ring_info *ring_data) | |||
| 3072 | } | 3040 | } |
| 3073 | } | 3041 | } |
| 3074 | } | 3042 | } |
| 3075 | |||
| 3076 | spin_unlock(&nic->rx_lock); | ||
| 3077 | } | 3043 | } |
| 3078 | 3044 | ||
| 3079 | /** | 3045 | /** |
| @@ -4105,7 +4071,6 @@ static int s2io_close(struct net_device *dev) | |||
| 4105 | do_s2io_delete_unicast_mc(sp, tmp64); | 4071 | do_s2io_delete_unicast_mc(sp, tmp64); |
| 4106 | } | 4072 | } |
| 4107 | 4073 | ||
| 4108 | /* Reset card, kill tasklet and free Tx and Rx buffers. */ | ||
| 4109 | s2io_card_down(sp); | 4074 | s2io_card_down(sp); |
| 4110 | 4075 | ||
| 4111 | return 0; | 4076 | return 0; |
| @@ -4370,29 +4335,9 @@ s2io_alarm_handle(unsigned long data) | |||
| 4370 | 4335 | ||
| 4371 | static int s2io_chk_rx_buffers(struct s2io_nic *sp, int rng_n) | 4336 | static int s2io_chk_rx_buffers(struct s2io_nic *sp, int rng_n) |
| 4372 | { | 4337 | { |
| 4373 | int rxb_size, level; | 4338 | if (fill_rx_buffers(sp, rng_n) == -ENOMEM) { |
| 4374 | 4339 | DBG_PRINT(INFO_DBG, "%s:Out of memory", sp->dev->name); | |
| 4375 | if (!sp->lro) { | 4340 | DBG_PRINT(INFO_DBG, " in Rx Intr!!\n"); |
| 4376 | rxb_size = atomic_read(&sp->rx_bufs_left[rng_n]); | ||
| 4377 | level = rx_buffer_level(sp, rxb_size, rng_n); | ||
| 4378 | |||
| 4379 | if ((level == PANIC) && (!TASKLET_IN_USE)) { | ||
| 4380 | int ret; | ||
| 4381 | DBG_PRINT(INTR_DBG, "%s: Rx BD hit ", __FUNCTION__); | ||
| 4382 | DBG_PRINT(INTR_DBG, "PANIC levels\n"); | ||
| 4383 | if ((ret = fill_rx_buffers(sp, rng_n)) == -ENOMEM) { | ||
| 4384 | DBG_PRINT(INFO_DBG, "Out of memory in %s", | ||
| 4385 | __FUNCTION__); | ||
| 4386 | clear_bit(0, (&sp->tasklet_status)); | ||
| 4387 | return -1; | ||
| 4388 | } | ||
| 4389 | clear_bit(0, (&sp->tasklet_status)); | ||
| 4390 | } else if (level == LOW) | ||
| 4391 | tasklet_schedule(&sp->task); | ||
| 4392 | |||
| 4393 | } else if (fill_rx_buffers(sp, rng_n) == -ENOMEM) { | ||
| 4394 | DBG_PRINT(INFO_DBG, "%s:Out of memory", sp->dev->name); | ||
| 4395 | DBG_PRINT(INFO_DBG, " in Rx Intr!!\n"); | ||
| 4396 | } | 4341 | } |
| 4397 | return 0; | 4342 | return 0; |
| 4398 | } | 4343 | } |
| @@ -6770,49 +6715,6 @@ static int s2io_change_mtu(struct net_device *dev, int new_mtu) | |||
| 6770 | } | 6715 | } |
| 6771 | 6716 | ||
| 6772 | /** | 6717 | /** |
| 6773 | * s2io_tasklet - Bottom half of the ISR. | ||
| 6774 | * @dev_adr : address of the device structure in dma_addr_t format. | ||
| 6775 | * Description: | ||
| 6776 | * This is the tasklet or the bottom half of the ISR. This is | ||
| 6777 | * an extension of the ISR which is scheduled by the scheduler to be run | ||
| 6778 | * when the load on the CPU is low. All low priority tasks of the ISR can | ||
| 6779 | * be pushed into the tasklet. For now the tasklet is used only to | ||
| 6780 | * replenish the Rx buffers in the Rx buffer descriptors. | ||
| 6781 | * Return value: | ||
| 6782 | * void. | ||
| 6783 | */ | ||
| 6784 | |||
| 6785 | static void s2io_tasklet(unsigned long dev_addr) | ||
| 6786 | { | ||
| 6787 | struct net_device *dev = (struct net_device *) dev_addr; | ||
| 6788 | struct s2io_nic *sp = dev->priv; | ||
| 6789 | int i, ret; | ||
| 6790 | struct mac_info *mac_control; | ||
| 6791 | struct config_param *config; | ||
| 6792 | |||
| 6793 | mac_control = &sp->mac_control; | ||
| 6794 | config = &sp->config; | ||
| 6795 | |||
| 6796 | if (!TASKLET_IN_USE) { | ||
| 6797 | for (i = 0; i < config->rx_ring_num; i++) { | ||
| 6798 | ret = fill_rx_buffers(sp, i); | ||
| 6799 | if (ret == -ENOMEM) { | ||
| 6800 | DBG_PRINT(INFO_DBG, "%s: Out of ", | ||
| 6801 | dev->name); | ||
| 6802 | DBG_PRINT(INFO_DBG, "memory in tasklet\n"); | ||
| 6803 | break; | ||
| 6804 | } else if (ret == -EFILL) { | ||
| 6805 | DBG_PRINT(INFO_DBG, | ||
| 6806 | "%s: Rx Ring %d is full\n", | ||
| 6807 | dev->name, i); | ||
| 6808 | break; | ||
| 6809 | } | ||
| 6810 | } | ||
| 6811 | clear_bit(0, (&sp->tasklet_status)); | ||
| 6812 | } | ||
| 6813 | } | ||
| 6814 | |||
| 6815 | /** | ||
| 6816 | * s2io_set_link - Set the LInk status | 6718 | * s2io_set_link - Set the LInk status |
| 6817 | * @data: long pointer to device private structue | 6719 | * @data: long pointer to device private structue |
| 6818 | * Description: Sets the link status for the adapter | 6720 | * Description: Sets the link status for the adapter |
| @@ -7161,7 +7063,6 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io) | |||
| 7161 | { | 7063 | { |
| 7162 | int cnt = 0; | 7064 | int cnt = 0; |
| 7163 | struct XENA_dev_config __iomem *bar0 = sp->bar0; | 7065 | struct XENA_dev_config __iomem *bar0 = sp->bar0; |
| 7164 | unsigned long flags; | ||
| 7165 | register u64 val64 = 0; | 7066 | register u64 val64 = 0; |
| 7166 | struct config_param *config; | 7067 | struct config_param *config; |
| 7167 | config = &sp->config; | 7068 | config = &sp->config; |
| @@ -7186,9 +7087,6 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io) | |||
| 7186 | 7087 | ||
| 7187 | s2io_rem_isr(sp); | 7088 | s2io_rem_isr(sp); |
| 7188 | 7089 | ||
| 7189 | /* Kill tasklet. */ | ||
| 7190 | tasklet_kill(&sp->task); | ||
| 7191 | |||
| 7192 | /* Check if the device is Quiescent and then Reset the NIC */ | 7090 | /* Check if the device is Quiescent and then Reset the NIC */ |
| 7193 | while(do_io) { | 7091 | while(do_io) { |
| 7194 | /* As per the HW requirement we need to replenish the | 7092 | /* As per the HW requirement we need to replenish the |
| @@ -7223,9 +7121,7 @@ static void do_s2io_card_down(struct s2io_nic * sp, int do_io) | |||
| 7223 | free_tx_buffers(sp); | 7121 | free_tx_buffers(sp); |
| 7224 | 7122 | ||
| 7225 | /* Free all Rx buffers */ | 7123 | /* Free all Rx buffers */ |
| 7226 | spin_lock_irqsave(&sp->rx_lock, flags); | ||
| 7227 | free_rx_buffers(sp); | 7124 | free_rx_buffers(sp); |
| 7228 | spin_unlock_irqrestore(&sp->rx_lock, flags); | ||
| 7229 | 7125 | ||
| 7230 | clear_bit(__S2IO_STATE_LINK_TASK, &(sp->state)); | 7126 | clear_bit(__S2IO_STATE_LINK_TASK, &(sp->state)); |
| 7231 | } | 7127 | } |
| @@ -7314,9 +7210,6 @@ static int s2io_card_up(struct s2io_nic * sp) | |||
| 7314 | 7210 | ||
| 7315 | S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2)); | 7211 | S2IO_TIMER_CONF(sp->alarm_timer, s2io_alarm_handle, sp, (HZ/2)); |
| 7316 | 7212 | ||
| 7317 | /* Enable tasklet for the device */ | ||
| 7318 | tasklet_init(&sp->task, s2io_tasklet, (unsigned long) dev); | ||
| 7319 | |||
| 7320 | /* Enable select interrupts */ | 7213 | /* Enable select interrupts */ |
| 7321 | en_dis_err_alarms(sp, ENA_ALL_INTRS, ENABLE_INTRS); | 7214 | en_dis_err_alarms(sp, ENA_ALL_INTRS, ENABLE_INTRS); |
| 7322 | if (sp->config.intr_type != INTA) | 7215 | if (sp->config.intr_type != INTA) |
| @@ -8119,20 +8012,15 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre) | |||
| 8119 | s2io_reset(sp); | 8012 | s2io_reset(sp); |
| 8120 | 8013 | ||
| 8121 | /* | 8014 | /* |
| 8122 | * Initialize the tasklet status and link state flags | 8015 | * Initialize link state flags |
| 8123 | * and the card state parameter | 8016 | * and the card state parameter |
| 8124 | */ | 8017 | */ |
| 8125 | sp->tasklet_status = 0; | ||
| 8126 | sp->state = 0; | 8018 | sp->state = 0; |
| 8127 | 8019 | ||
| 8128 | /* Initialize spinlocks */ | 8020 | /* Initialize spinlocks */ |
| 8129 | for (i = 0; i < sp->config.tx_fifo_num; i++) | 8021 | for (i = 0; i < sp->config.tx_fifo_num; i++) |
| 8130 | spin_lock_init(&mac_control->fifos[i].tx_lock); | 8022 | spin_lock_init(&mac_control->fifos[i].tx_lock); |
| 8131 | 8023 | ||
| 8132 | if (!napi) | ||
| 8133 | spin_lock_init(&sp->put_lock); | ||
| 8134 | spin_lock_init(&sp->rx_lock); | ||
| 8135 | |||
| 8136 | /* | 8024 | /* |
| 8137 | * SXE-002: Configure link and activity LED to init state | 8025 | * SXE-002: Configure link and activity LED to init state |
| 8138 | * on driver load. | 8026 | * on driver load. |
diff --git a/drivers/net/s2io.h b/drivers/net/s2io.h index e68fdf7e4260..ce53a02105f2 100644 --- a/drivers/net/s2io.h +++ b/drivers/net/s2io.h | |||
| @@ -703,9 +703,6 @@ struct ring_info { | |||
| 703 | */ | 703 | */ |
| 704 | struct rx_curr_get_info rx_curr_get_info; | 704 | struct rx_curr_get_info rx_curr_get_info; |
| 705 | 705 | ||
| 706 | /* Index to the absolute position of the put pointer of Rx ring */ | ||
| 707 | int put_pos; | ||
| 708 | |||
| 709 | /* Buffer Address store. */ | 706 | /* Buffer Address store. */ |
| 710 | struct buffAdd **ba; | 707 | struct buffAdd **ba; |
| 711 | struct s2io_nic *nic; | 708 | struct s2io_nic *nic; |
| @@ -868,8 +865,6 @@ struct s2io_nic { | |||
| 868 | int device_enabled_once; | 865 | int device_enabled_once; |
| 869 | 866 | ||
| 870 | char name[60]; | 867 | char name[60]; |
| 871 | struct tasklet_struct task; | ||
| 872 | volatile unsigned long tasklet_status; | ||
| 873 | 868 | ||
| 874 | /* Timer that handles I/O errors/exceptions */ | 869 | /* Timer that handles I/O errors/exceptions */ |
| 875 | struct timer_list alarm_timer; | 870 | struct timer_list alarm_timer; |
| @@ -879,8 +874,6 @@ struct s2io_nic { | |||
| 879 | 874 | ||
| 880 | atomic_t rx_bufs_left[MAX_RX_RINGS]; | 875 | atomic_t rx_bufs_left[MAX_RX_RINGS]; |
| 881 | 876 | ||
| 882 | spinlock_t put_lock; | ||
| 883 | |||
| 884 | #define PROMISC 1 | 877 | #define PROMISC 1 |
| 885 | #define ALL_MULTI 2 | 878 | #define ALL_MULTI 2 |
| 886 | 879 | ||
| @@ -964,7 +957,6 @@ struct s2io_nic { | |||
| 964 | u8 lro; | 957 | u8 lro; |
| 965 | u16 lro_max_aggr_per_sess; | 958 | u16 lro_max_aggr_per_sess; |
| 966 | volatile unsigned long state; | 959 | volatile unsigned long state; |
| 967 | spinlock_t rx_lock; | ||
| 968 | u64 general_int_mask; | 960 | u64 general_int_mask; |
| 969 | #define VPD_STRING_LEN 80 | 961 | #define VPD_STRING_LEN 80 |
| 970 | u8 product_name[VPD_STRING_LEN]; | 962 | u8 product_name[VPD_STRING_LEN]; |
| @@ -1094,7 +1086,6 @@ static void s2io_handle_errors(void * dev_id); | |||
| 1094 | static int s2io_starter(void); | 1086 | static int s2io_starter(void); |
| 1095 | static void s2io_closer(void); | 1087 | static void s2io_closer(void); |
| 1096 | static void s2io_tx_watchdog(struct net_device *dev); | 1088 | static void s2io_tx_watchdog(struct net_device *dev); |
| 1097 | static void s2io_tasklet(unsigned long dev_addr); | ||
| 1098 | static void s2io_set_multicast(struct net_device *dev); | 1089 | static void s2io_set_multicast(struct net_device *dev); |
| 1099 | static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp); | 1090 | static int rx_osm_handler(struct ring_info *ring_data, struct RxD_t * rxdp); |
| 1100 | static void s2io_link(struct s2io_nic * sp, int link); | 1091 | static void s2io_link(struct s2io_nic * sp, int link); |
diff --git a/drivers/net/sgiseeq.c b/drivers/net/sgiseeq.c index 78994ede0cb0..6261201403cd 100644 --- a/drivers/net/sgiseeq.c +++ b/drivers/net/sgiseeq.c | |||
| @@ -825,7 +825,8 @@ static struct platform_driver sgiseeq_driver = { | |||
| 825 | .probe = sgiseeq_probe, | 825 | .probe = sgiseeq_probe, |
| 826 | .remove = __devexit_p(sgiseeq_remove), | 826 | .remove = __devexit_p(sgiseeq_remove), |
| 827 | .driver = { | 827 | .driver = { |
| 828 | .name = "sgiseeq" | 828 | .name = "sgiseeq", |
| 829 | .owner = THIS_MODULE, | ||
| 829 | } | 830 | } |
| 830 | }; | 831 | }; |
| 831 | 832 | ||
| @@ -850,3 +851,4 @@ module_exit(sgiseeq_module_exit); | |||
| 850 | MODULE_DESCRIPTION("SGI Seeq 8003 driver"); | 851 | MODULE_DESCRIPTION("SGI Seeq 8003 driver"); |
| 851 | MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>"); | 852 | MODULE_AUTHOR("Linux/MIPS Mailing List <linux-mips@linux-mips.org>"); |
| 852 | MODULE_LICENSE("GPL"); | 853 | MODULE_LICENSE("GPL"); |
| 854 | MODULE_ALIAS("platform:sgiseeq"); | ||
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 76cc1d3adf71..4e2800205189 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c | |||
| @@ -92,6 +92,7 @@ module_param(tx_fifo_kb, int, 0400); | |||
| 92 | MODULE_PARM_DESC(tx_fifo_kb,"transmit FIFO size in KB (1<x<15)(default=8)"); | 92 | MODULE_PARM_DESC(tx_fifo_kb,"transmit FIFO size in KB (1<x<15)(default=8)"); |
| 93 | 93 | ||
| 94 | MODULE_LICENSE("GPL"); | 94 | MODULE_LICENSE("GPL"); |
| 95 | MODULE_ALIAS("platform:smc911x"); | ||
| 95 | 96 | ||
| 96 | /* | 97 | /* |
| 97 | * The internal workings of the driver. If you are changing anything | 98 | * The internal workings of the driver. If you are changing anything |
| @@ -243,7 +244,7 @@ static void smc911x_reset(struct net_device *dev) | |||
| 243 | do { | 244 | do { |
| 244 | udelay(10); | 245 | udelay(10); |
| 245 | reg = SMC_GET_PMT_CTRL() & PMT_CTRL_READY_; | 246 | reg = SMC_GET_PMT_CTRL() & PMT_CTRL_READY_; |
| 246 | } while ( timeout-- && !reg); | 247 | } while (--timeout && !reg); |
| 247 | if (timeout == 0) { | 248 | if (timeout == 0) { |
| 248 | PRINTK("%s: smc911x_reset timeout waiting for PM restore\n", dev->name); | 249 | PRINTK("%s: smc911x_reset timeout waiting for PM restore\n", dev->name); |
| 249 | return; | 250 | return; |
| @@ -267,7 +268,7 @@ static void smc911x_reset(struct net_device *dev) | |||
| 267 | resets++; | 268 | resets++; |
| 268 | break; | 269 | break; |
| 269 | } | 270 | } |
| 270 | } while ( timeout-- && (reg & HW_CFG_SRST_)); | 271 | } while (--timeout && (reg & HW_CFG_SRST_)); |
| 271 | } | 272 | } |
| 272 | if (timeout == 0) { | 273 | if (timeout == 0) { |
| 273 | PRINTK("%s: smc911x_reset timeout waiting for reset\n", dev->name); | 274 | PRINTK("%s: smc911x_reset timeout waiting for reset\n", dev->name); |
| @@ -413,7 +414,7 @@ static inline void smc911x_drop_pkt(struct net_device *dev) | |||
| 413 | do { | 414 | do { |
| 414 | udelay(10); | 415 | udelay(10); |
| 415 | reg = SMC_GET_RX_DP_CTRL() & RX_DP_CTRL_FFWD_BUSY_; | 416 | reg = SMC_GET_RX_DP_CTRL() & RX_DP_CTRL_FFWD_BUSY_; |
| 416 | } while ( timeout-- && reg); | 417 | } while (--timeout && reg); |
| 417 | if (timeout == 0) { | 418 | if (timeout == 0) { |
| 418 | PRINTK("%s: timeout waiting for RX fast forward\n", dev->name); | 419 | PRINTK("%s: timeout waiting for RX fast forward\n", dev->name); |
| 419 | } | 420 | } |
| @@ -2262,6 +2263,7 @@ static struct platform_driver smc911x_driver = { | |||
| 2262 | .resume = smc911x_drv_resume, | 2263 | .resume = smc911x_drv_resume, |
| 2263 | .driver = { | 2264 | .driver = { |
| 2264 | .name = CARDNAME, | 2265 | .name = CARDNAME, |
| 2266 | .owner = THIS_MODULE, | ||
| 2265 | }, | 2267 | }, |
| 2266 | }; | 2268 | }; |
| 2267 | 2269 | ||
diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 600b92af3334..a188e33484e6 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c | |||
| @@ -132,6 +132,7 @@ module_param(watchdog, int, 0400); | |||
| 132 | MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); | 132 | MODULE_PARM_DESC(watchdog, "transmit timeout in milliseconds"); |
| 133 | 133 | ||
| 134 | MODULE_LICENSE("GPL"); | 134 | MODULE_LICENSE("GPL"); |
| 135 | MODULE_ALIAS("platform:smc91x"); | ||
| 135 | 136 | ||
| 136 | /* | 137 | /* |
| 137 | * The internal workings of the driver. If you are changing anything | 138 | * The internal workings of the driver. If you are changing anything |
| @@ -2308,6 +2309,7 @@ static struct platform_driver smc_driver = { | |||
| 2308 | .resume = smc_drv_resume, | 2309 | .resume = smc_drv_resume, |
| 2309 | .driver = { | 2310 | .driver = { |
| 2310 | .name = CARDNAME, | 2311 | .name = CARDNAME, |
| 2312 | .owner = THIS_MODULE, | ||
| 2311 | }, | 2313 | }, |
| 2312 | }; | 2314 | }; |
| 2313 | 2315 | ||
diff --git a/drivers/net/sni_82596.c b/drivers/net/sni_82596.c index 2cf6794acb4f..854ccf2b4105 100644 --- a/drivers/net/sni_82596.c +++ b/drivers/net/sni_82596.c | |||
| @@ -44,6 +44,7 @@ static const char sni_82596_string[] = "snirm_82596"; | |||
| 44 | MODULE_AUTHOR("Thomas Bogendoerfer"); | 44 | MODULE_AUTHOR("Thomas Bogendoerfer"); |
| 45 | MODULE_DESCRIPTION("i82596 driver"); | 45 | MODULE_DESCRIPTION("i82596 driver"); |
| 46 | MODULE_LICENSE("GPL"); | 46 | MODULE_LICENSE("GPL"); |
| 47 | MODULE_ALIAS("platform:snirm_82596"); | ||
| 47 | module_param(i596_debug, int, 0); | 48 | module_param(i596_debug, int, 0); |
| 48 | MODULE_PARM_DESC(i596_debug, "82596 debug mask"); | 49 | MODULE_PARM_DESC(i596_debug, "82596 debug mask"); |
| 49 | 50 | ||
| @@ -166,6 +167,7 @@ static struct platform_driver sni_82596_driver = { | |||
| 166 | .remove = __devexit_p(sni_82596_driver_remove), | 167 | .remove = __devexit_p(sni_82596_driver_remove), |
| 167 | .driver = { | 168 | .driver = { |
| 168 | .name = sni_82596_string, | 169 | .name = sni_82596_string, |
| 170 | .owner = THIS_MODULE, | ||
| 169 | }, | 171 | }, |
| 170 | }; | 172 | }; |
| 171 | 173 | ||
diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c index 17585e5eed53..e83b166aa6b9 100644 --- a/drivers/net/tehuti.c +++ b/drivers/net/tehuti.c | |||
| @@ -625,6 +625,12 @@ static void __init bdx_firmware_endianess(void) | |||
| 625 | s_firmLoad[i] = CPU_CHIP_SWAP32(s_firmLoad[i]); | 625 | s_firmLoad[i] = CPU_CHIP_SWAP32(s_firmLoad[i]); |
| 626 | } | 626 | } |
| 627 | 627 | ||
| 628 | static int bdx_range_check(struct bdx_priv *priv, u32 offset) | ||
| 629 | { | ||
| 630 | return (offset > (u32) (BDX_REGS_SIZE / priv->nic->port_num)) ? | ||
| 631 | -EINVAL : 0; | ||
| 632 | } | ||
| 633 | |||
| 628 | static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd) | 634 | static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd) |
| 629 | { | 635 | { |
| 630 | struct bdx_priv *priv = ndev->priv; | 636 | struct bdx_priv *priv = ndev->priv; |
| @@ -643,9 +649,15 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd) | |||
| 643 | DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]); | 649 | DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]); |
| 644 | } | 650 | } |
| 645 | 651 | ||
| 652 | if (!capable(CAP_NET_ADMIN)) | ||
| 653 | return -EPERM; | ||
| 654 | |||
| 646 | switch (data[0]) { | 655 | switch (data[0]) { |
| 647 | 656 | ||
| 648 | case BDX_OP_READ: | 657 | case BDX_OP_READ: |
| 658 | error = bdx_range_check(priv, data[1]); | ||
| 659 | if (error < 0) | ||
| 660 | return error; | ||
| 649 | data[2] = READ_REG(priv, data[1]); | 661 | data[2] = READ_REG(priv, data[1]); |
| 650 | DBG("read_reg(0x%x)=0x%x (dec %d)\n", data[1], data[2], | 662 | DBG("read_reg(0x%x)=0x%x (dec %d)\n", data[1], data[2], |
| 651 | data[2]); | 663 | data[2]); |
| @@ -655,6 +667,9 @@ static int bdx_ioctl_priv(struct net_device *ndev, struct ifreq *ifr, int cmd) | |||
| 655 | break; | 667 | break; |
| 656 | 668 | ||
| 657 | case BDX_OP_WRITE: | 669 | case BDX_OP_WRITE: |
| 670 | error = bdx_range_check(priv, data[1]); | ||
| 671 | if (error < 0) | ||
| 672 | return error; | ||
| 658 | WRITE_REG(priv, data[1], data[2]); | 673 | WRITE_REG(priv, data[1], data[2]); |
| 659 | DBG("write_reg(0x%x, 0x%x)\n", data[1], data[2]); | 674 | DBG("write_reg(0x%x, 0x%x)\n", data[1], data[2]); |
| 660 | break; | 675 | break; |
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index bc4c62b8e81a..e3f74c9f78bd 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
| @@ -4017,6 +4017,8 @@ static int tg3_halt(struct tg3 *, int, int); | |||
| 4017 | * Invoked with tp->lock held. | 4017 | * Invoked with tp->lock held. |
| 4018 | */ | 4018 | */ |
| 4019 | static int tg3_restart_hw(struct tg3 *tp, int reset_phy) | 4019 | static int tg3_restart_hw(struct tg3 *tp, int reset_phy) |
| 4020 | __releases(tp->lock) | ||
| 4021 | __acquires(tp->lock) | ||
| 4020 | { | 4022 | { |
| 4021 | int err; | 4023 | int err; |
| 4022 | 4024 | ||
diff --git a/drivers/net/tsi108_eth.c b/drivers/net/tsi108_eth.c index 6f33f84d37b0..6017d5267d08 100644 --- a/drivers/net/tsi108_eth.c +++ b/drivers/net/tsi108_eth.c | |||
| @@ -162,6 +162,7 @@ static struct platform_driver tsi_eth_driver = { | |||
| 162 | .remove = tsi108_ether_remove, | 162 | .remove = tsi108_ether_remove, |
| 163 | .driver = { | 163 | .driver = { |
| 164 | .name = "tsi-ethernet", | 164 | .name = "tsi-ethernet", |
| 165 | .owner = THIS_MODULE, | ||
| 165 | }, | 166 | }, |
| 166 | }; | 167 | }; |
| 167 | 168 | ||
| @@ -1729,3 +1730,4 @@ module_exit(tsi108_ether_exit); | |||
| 1729 | MODULE_AUTHOR("Tundra Semiconductor Corporation"); | 1730 | MODULE_AUTHOR("Tundra Semiconductor Corporation"); |
| 1730 | MODULE_DESCRIPTION("Tsi108 Gigabit Ethernet driver"); | 1731 | MODULE_DESCRIPTION("Tsi108 Gigabit Ethernet driver"); |
| 1731 | MODULE_LICENSE("GPL"); | 1732 | MODULE_LICENSE("GPL"); |
| 1733 | MODULE_ALIAS("platform:tsi-ethernet"); | ||
diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 333961bb7873..c0dd25ba7a18 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c | |||
| @@ -2183,7 +2183,6 @@ typhoon_resume(struct pci_dev *pdev) | |||
| 2183 | } | 2183 | } |
| 2184 | 2184 | ||
| 2185 | netif_device_attach(dev); | 2185 | netif_device_attach(dev); |
| 2186 | netif_start_queue(dev); | ||
| 2187 | return 0; | 2186 | return 0; |
| 2188 | 2187 | ||
| 2189 | reset: | 2188 | reset: |
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 2f11254bcc07..281ce3d39532 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c | |||
| @@ -3932,7 +3932,7 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma | |||
| 3932 | ug_info->uf_info.irq = irq_of_parse_and_map(np, 0); | 3932 | ug_info->uf_info.irq = irq_of_parse_and_map(np, 0); |
| 3933 | fixed_link = of_get_property(np, "fixed-link", NULL); | 3933 | fixed_link = of_get_property(np, "fixed-link", NULL); |
| 3934 | if (fixed_link) { | 3934 | if (fixed_link) { |
| 3935 | ug_info->mdio_bus = 0; | 3935 | snprintf(ug_info->mdio_bus, MII_BUS_ID_SIZE, "0"); |
| 3936 | ug_info->phy_address = fixed_link[0]; | 3936 | ug_info->phy_address = fixed_link[0]; |
| 3937 | phy = NULL; | 3937 | phy = NULL; |
| 3938 | } else { | 3938 | } else { |
diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index ed1afaf683a4..6b8d882d197b 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c | |||
| @@ -605,7 +605,6 @@ static void __devinit velocity_get_options(struct velocity_opt *opts, int index, | |||
| 605 | static void velocity_init_cam_filter(struct velocity_info *vptr) | 605 | static void velocity_init_cam_filter(struct velocity_info *vptr) |
| 606 | { | 606 | { |
| 607 | struct mac_regs __iomem * regs = vptr->mac_regs; | 607 | struct mac_regs __iomem * regs = vptr->mac_regs; |
| 608 | unsigned short vid; | ||
| 609 | 608 | ||
| 610 | /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */ | 609 | /* Turn on MCFG_PQEN, turn off MCFG_RTGOPT */ |
| 611 | WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, ®s->MCFG); | 610 | WORD_REG_BITS_SET(MCFG_PQEN, MCFG_RTGOPT, ®s->MCFG); |
| @@ -617,29 +616,33 @@ static void velocity_init_cam_filter(struct velocity_info *vptr) | |||
| 617 | mac_set_vlan_cam_mask(regs, vptr->vCAMmask); | 616 | mac_set_vlan_cam_mask(regs, vptr->vCAMmask); |
| 618 | mac_set_cam_mask(regs, vptr->mCAMmask); | 617 | mac_set_cam_mask(regs, vptr->mCAMmask); |
| 619 | 618 | ||
| 620 | /* Enable first VCAM */ | 619 | /* Enable VCAMs */ |
| 621 | if (vptr->vlgrp) { | 620 | if (vptr->vlgrp) { |
| 622 | for (vid = 0; vid < VLAN_VID_MASK; vid++) { | 621 | unsigned int vid, i = 0; |
| 623 | if (vlan_group_get_device(vptr->vlgrp, vid)) { | 622 | |
| 624 | /* If Tagging option is enabled and | 623 | if (!vlan_group_get_device(vptr->vlgrp, 0)) |
| 625 | VLAN ID is not zero, then | 624 | WORD_REG_BITS_ON(MCFG_RTGOPT, ®s->MCFG); |
| 626 | turn on MCFG_RTGOPT also */ | ||
| 627 | if (vid != 0) | ||
| 628 | WORD_REG_BITS_ON(MCFG_RTGOPT, ®s->MCFG); | ||
| 629 | 625 | ||
| 630 | mac_set_vlan_cam(regs, 0, (u8 *) &vid); | 626 | for (vid = 1; (vid < VLAN_VID_MASK); vid++) { |
| 627 | if (vlan_group_get_device(vptr->vlgrp, vid)) { | ||
| 628 | mac_set_vlan_cam(regs, i, (u8 *) &vid); | ||
| 629 | vptr->vCAMmask[i / 8] |= 0x1 << (i % 8); | ||
| 630 | if (++i >= VCAM_SIZE) | ||
| 631 | break; | ||
| 631 | } | 632 | } |
| 632 | } | 633 | } |
| 633 | vptr->vCAMmask[0] |= 1; | ||
| 634 | mac_set_vlan_cam_mask(regs, vptr->vCAMmask); | 634 | mac_set_vlan_cam_mask(regs, vptr->vCAMmask); |
| 635 | } else { | ||
| 636 | u16 temp = 0; | ||
| 637 | mac_set_vlan_cam(regs, 0, (u8 *) &temp); | ||
| 638 | temp = 1; | ||
| 639 | mac_set_vlan_cam_mask(regs, (u8 *) &temp); | ||
| 640 | } | 635 | } |
| 641 | } | 636 | } |
| 642 | 637 | ||
| 638 | static void velocity_vlan_rx_register(struct net_device *dev, | ||
| 639 | struct vlan_group *grp) | ||
| 640 | { | ||
| 641 | struct velocity_info *vptr = netdev_priv(dev); | ||
| 642 | |||
| 643 | vptr->vlgrp = grp; | ||
| 644 | } | ||
| 645 | |||
| 643 | static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) | 646 | static void velocity_vlan_rx_add_vid(struct net_device *dev, unsigned short vid) |
| 644 | { | 647 | { |
| 645 | struct velocity_info *vptr = netdev_priv(dev); | 648 | struct velocity_info *vptr = netdev_priv(dev); |
| @@ -959,11 +962,13 @@ static int __devinit velocity_found1(struct pci_dev *pdev, const struct pci_devi | |||
| 959 | 962 | ||
| 960 | dev->vlan_rx_add_vid = velocity_vlan_rx_add_vid; | 963 | dev->vlan_rx_add_vid = velocity_vlan_rx_add_vid; |
| 961 | dev->vlan_rx_kill_vid = velocity_vlan_rx_kill_vid; | 964 | dev->vlan_rx_kill_vid = velocity_vlan_rx_kill_vid; |
| 965 | dev->vlan_rx_register = velocity_vlan_rx_register; | ||
| 962 | 966 | ||
| 963 | #ifdef VELOCITY_ZERO_COPY_SUPPORT | 967 | #ifdef VELOCITY_ZERO_COPY_SUPPORT |
| 964 | dev->features |= NETIF_F_SG; | 968 | dev->features |= NETIF_F_SG; |
| 965 | #endif | 969 | #endif |
| 966 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER; | 970 | dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | |
| 971 | NETIF_F_HW_VLAN_RX; | ||
| 967 | 972 | ||
| 968 | if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) | 973 | if (vptr->flags & VELOCITY_FLAGS_TX_CSUM) |
| 969 | dev->features |= NETIF_F_IP_CSUM; | 974 | dev->features |= NETIF_F_IP_CSUM; |
| @@ -1597,8 +1602,13 @@ static int velocity_receive_frame(struct velocity_info *vptr, int idx) | |||
| 1597 | skb_put(skb, pkt_len - 4); | 1602 | skb_put(skb, pkt_len - 4); |
| 1598 | skb->protocol = eth_type_trans(skb, vptr->dev); | 1603 | skb->protocol = eth_type_trans(skb, vptr->dev); |
| 1599 | 1604 | ||
| 1605 | if (vptr->vlgrp && (rd->rdesc0.RSR & RSR_DETAG)) { | ||
| 1606 | vlan_hwaccel_rx(skb, vptr->vlgrp, | ||
| 1607 | swab16(le16_to_cpu(rd->rdesc1.PQTAG))); | ||
| 1608 | } else | ||
| 1609 | netif_rx(skb); | ||
| 1610 | |||
| 1600 | stats->rx_bytes += pkt_len; | 1611 | stats->rx_bytes += pkt_len; |
| 1601 | netif_rx(skb); | ||
| 1602 | 1612 | ||
| 1603 | return 0; | 1613 | return 0; |
| 1604 | } | 1614 | } |
diff --git a/drivers/net/wan/c101.c b/drivers/net/wan/c101.c index c4c8eab8574f..c2cc42f723d5 100644 --- a/drivers/net/wan/c101.c +++ b/drivers/net/wan/c101.c | |||
| @@ -402,7 +402,7 @@ static int __init c101_init(void) | |||
| 402 | #ifdef MODULE | 402 | #ifdef MODULE |
| 403 | printk(KERN_INFO "c101: no card initialized\n"); | 403 | printk(KERN_INFO "c101: no card initialized\n"); |
| 404 | #endif | 404 | #endif |
| 405 | return -ENOSYS; /* no parameters specified, abort */ | 405 | return -EINVAL; /* no parameters specified, abort */ |
| 406 | } | 406 | } |
| 407 | 407 | ||
| 408 | printk(KERN_INFO "%s\n", version); | 408 | printk(KERN_INFO "%s\n", version); |
| @@ -420,11 +420,11 @@ static int __init c101_init(void) | |||
| 420 | c101_run(irq, ram); | 420 | c101_run(irq, ram); |
| 421 | 421 | ||
| 422 | if (*hw == '\x0') | 422 | if (*hw == '\x0') |
| 423 | return first_card ? 0 : -ENOSYS; | 423 | return first_card ? 0 : -EINVAL; |
| 424 | }while(*hw++ == ':'); | 424 | }while(*hw++ == ':'); |
| 425 | 425 | ||
| 426 | printk(KERN_ERR "c101: invalid hardware parameters\n"); | 426 | printk(KERN_ERR "c101: invalid hardware parameters\n"); |
| 427 | return first_card ? 0 : -ENOSYS; | 427 | return first_card ? 0 : -EINVAL; |
| 428 | } | 428 | } |
| 429 | 429 | ||
| 430 | 430 | ||
diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index c4ab0326f911..520bb0b1a9a2 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c | |||
| @@ -1090,10 +1090,6 @@ static int fr_add_pvc(struct net_device *frad, unsigned int dlci, int type) | |||
| 1090 | pvc_device *pvc = NULL; | 1090 | pvc_device *pvc = NULL; |
| 1091 | struct net_device *dev; | 1091 | struct net_device *dev; |
| 1092 | int result, used; | 1092 | int result, used; |
| 1093 | char * prefix = "pvc%d"; | ||
| 1094 | |||
| 1095 | if (type == ARPHRD_ETHER) | ||
| 1096 | prefix = "pvceth%d"; | ||
| 1097 | 1093 | ||
| 1098 | if ((pvc = add_pvc(frad, dlci)) == NULL) { | 1094 | if ((pvc = add_pvc(frad, dlci)) == NULL) { |
| 1099 | printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n", | 1095 | printk(KERN_WARNING "%s: Memory squeeze on fr_add_pvc()\n", |
diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking index d14d5a4dc5ac..3ea36554107f 100644 --- a/fs/jffs2/README.Locking +++ b/fs/jffs2/README.Locking | |||
| @@ -14,7 +14,7 @@ be fairly close. | |||
| 14 | alloc_sem | 14 | alloc_sem |
| 15 | --------- | 15 | --------- |
| 16 | 16 | ||
| 17 | The alloc_sem is a per-filesystem semaphore, used primarily to ensure | 17 | The alloc_sem is a per-filesystem mutex, used primarily to ensure |
| 18 | contiguous allocation of space on the medium. It is automatically | 18 | contiguous allocation of space on the medium. It is automatically |
| 19 | obtained during space allocations (jffs2_reserve_space()) and freed | 19 | obtained during space allocations (jffs2_reserve_space()) and freed |
| 20 | upon write completion (jffs2_complete_reservation()). Note that | 20 | upon write completion (jffs2_complete_reservation()). Note that |
| @@ -41,10 +41,10 @@ if the wbuf is currently holding any data is permitted, though. | |||
| 41 | Ordering constraints: See f->sem. | 41 | Ordering constraints: See f->sem. |
| 42 | 42 | ||
| 43 | 43 | ||
| 44 | File Semaphore f->sem | 44 | File Mutex f->sem |
| 45 | --------------------- | 45 | --------------------- |
| 46 | 46 | ||
| 47 | This is the JFFS2-internal equivalent of the inode semaphore i->i_sem. | 47 | This is the JFFS2-internal equivalent of the inode mutex i->i_sem. |
| 48 | It protects the contents of the jffs2_inode_info private inode data, | 48 | It protects the contents of the jffs2_inode_info private inode data, |
| 49 | including the linked list of node fragments (but see the notes below on | 49 | including the linked list of node fragments (but see the notes below on |
| 50 | erase_completion_lock), etc. | 50 | erase_completion_lock), etc. |
| @@ -60,14 +60,14 @@ lead to deadlock, unless we played games with unlocking the i_sem | |||
| 60 | before calling the space allocation functions. | 60 | before calling the space allocation functions. |
| 61 | 61 | ||
| 62 | Instead of playing such games, we just have an extra internal | 62 | Instead of playing such games, we just have an extra internal |
| 63 | semaphore, which is obtained by the garbage collection code and also | 63 | mutex, which is obtained by the garbage collection code and also |
| 64 | by the normal file system code _after_ allocation of space. | 64 | by the normal file system code _after_ allocation of space. |
| 65 | 65 | ||
| 66 | Ordering constraints: | 66 | Ordering constraints: |
| 67 | 67 | ||
| 68 | 1. Never attempt to allocate space or lock alloc_sem with | 68 | 1. Never attempt to allocate space or lock alloc_sem with |
| 69 | any f->sem held. | 69 | any f->sem held. |
| 70 | 2. Never attempt to lock two file semaphores in one thread. | 70 | 2. Never attempt to lock two file mutexes in one thread. |
| 71 | No ordering rules have been made for doing so. | 71 | No ordering rules have been made for doing so. |
| 72 | 72 | ||
| 73 | 73 | ||
| @@ -86,8 +86,8 @@ a simple spin_lock() rather than spin_lock_bh(). | |||
| 86 | 86 | ||
| 87 | Note that the per-inode list of physical nodes (f->nodes) is a special | 87 | Note that the per-inode list of physical nodes (f->nodes) is a special |
| 88 | case. Any changes to _valid_ nodes (i.e. ->flash_offset & 1 == 0) in | 88 | case. Any changes to _valid_ nodes (i.e. ->flash_offset & 1 == 0) in |
| 89 | the list are protected by the file semaphore f->sem. But the erase | 89 | the list are protected by the file mutex f->sem. But the erase code |
| 90 | code may remove _obsolete_ nodes from the list while holding only the | 90 | may remove _obsolete_ nodes from the list while holding only the |
| 91 | erase_completion_lock. So you can walk the list only while holding the | 91 | erase_completion_lock. So you can walk the list only while holding the |
| 92 | erase_completion_lock, and can drop the lock temporarily mid-walk as | 92 | erase_completion_lock, and can drop the lock temporarily mid-walk as |
| 93 | long as the pointer you're holding is to a _valid_ node, not an | 93 | long as the pointer you're holding is to a _valid_ node, not an |
| @@ -124,10 +124,10 @@ Ordering constraints: | |||
| 124 | erase_free_sem | 124 | erase_free_sem |
| 125 | -------------- | 125 | -------------- |
| 126 | 126 | ||
| 127 | This semaphore is only used by the erase code which frees obsolete | 127 | This mutex is only used by the erase code which frees obsolete node |
| 128 | node references and the jffs2_garbage_collect_deletion_dirent() | 128 | references and the jffs2_garbage_collect_deletion_dirent() function. |
| 129 | function. The latter function on NAND flash must read _obsolete_ nodes | 129 | The latter function on NAND flash must read _obsolete_ nodes to |
| 130 | to determine whether the 'deletion dirent' under consideration can be | 130 | determine whether the 'deletion dirent' under consideration can be |
| 131 | discarded or whether it is still required to show that an inode has | 131 | discarded or whether it is still required to show that an inode has |
| 132 | been unlinked. Because reading from the flash may sleep, the | 132 | been unlinked. Because reading from the flash may sleep, the |
| 133 | erase_completion_lock cannot be held, so an alternative, more | 133 | erase_completion_lock cannot be held, so an alternative, more |
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index 722a6b682951..d58f845ccb85 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c | |||
| @@ -345,6 +345,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) | |||
| 345 | INIT_LIST_HEAD(&c->dirty_list); | 345 | INIT_LIST_HEAD(&c->dirty_list); |
| 346 | INIT_LIST_HEAD(&c->erasable_list); | 346 | INIT_LIST_HEAD(&c->erasable_list); |
| 347 | INIT_LIST_HEAD(&c->erasing_list); | 347 | INIT_LIST_HEAD(&c->erasing_list); |
| 348 | INIT_LIST_HEAD(&c->erase_checking_list); | ||
| 348 | INIT_LIST_HEAD(&c->erase_pending_list); | 349 | INIT_LIST_HEAD(&c->erase_pending_list); |
| 349 | INIT_LIST_HEAD(&c->erasable_pending_wbuf_list); | 350 | INIT_LIST_HEAD(&c->erasable_pending_wbuf_list); |
| 350 | INIT_LIST_HEAD(&c->erase_complete_list); | 351 | INIT_LIST_HEAD(&c->erase_complete_list); |
diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index 3a32c64ed497..5544d31c066b 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c | |||
| @@ -62,9 +62,9 @@ __jffs2_dbg_acct_sanity_check(struct jffs2_sb_info *c, | |||
| 62 | void | 62 | void |
| 63 | __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) | 63 | __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) |
| 64 | { | 64 | { |
| 65 | down(&f->sem); | 65 | mutex_lock(&f->sem); |
| 66 | __jffs2_dbg_fragtree_paranoia_check_nolock(f); | 66 | __jffs2_dbg_fragtree_paranoia_check_nolock(f); |
| 67 | up(&f->sem); | 67 | mutex_unlock(&f->sem); |
| 68 | } | 68 | } |
| 69 | 69 | ||
| 70 | void | 70 | void |
| @@ -153,6 +153,139 @@ __jffs2_dbg_prewrite_paranoia_check(struct jffs2_sb_info *c, | |||
| 153 | kfree(buf); | 153 | kfree(buf); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | void __jffs2_dbg_superblock_counts(struct jffs2_sb_info *c) | ||
| 157 | { | ||
| 158 | struct jffs2_eraseblock *jeb; | ||
| 159 | uint32_t free = 0, dirty = 0, used = 0, wasted = 0, | ||
| 160 | erasing = 0, bad = 0, unchecked = 0; | ||
| 161 | int nr_counted = 0; | ||
| 162 | int dump = 0; | ||
| 163 | |||
| 164 | if (c->gcblock) { | ||
| 165 | nr_counted++; | ||
| 166 | free += c->gcblock->free_size; | ||
| 167 | dirty += c->gcblock->dirty_size; | ||
| 168 | used += c->gcblock->used_size; | ||
| 169 | wasted += c->gcblock->wasted_size; | ||
| 170 | unchecked += c->gcblock->unchecked_size; | ||
| 171 | } | ||
| 172 | if (c->nextblock) { | ||
| 173 | nr_counted++; | ||
| 174 | free += c->nextblock->free_size; | ||
| 175 | dirty += c->nextblock->dirty_size; | ||
| 176 | used += c->nextblock->used_size; | ||
| 177 | wasted += c->nextblock->wasted_size; | ||
| 178 | unchecked += c->nextblock->unchecked_size; | ||
| 179 | } | ||
| 180 | list_for_each_entry(jeb, &c->clean_list, list) { | ||
| 181 | nr_counted++; | ||
| 182 | free += jeb->free_size; | ||
| 183 | dirty += jeb->dirty_size; | ||
| 184 | used += jeb->used_size; | ||
| 185 | wasted += jeb->wasted_size; | ||
| 186 | unchecked += jeb->unchecked_size; | ||
| 187 | } | ||
| 188 | list_for_each_entry(jeb, &c->very_dirty_list, list) { | ||
| 189 | nr_counted++; | ||
| 190 | free += jeb->free_size; | ||
| 191 | dirty += jeb->dirty_size; | ||
| 192 | used += jeb->used_size; | ||
| 193 | wasted += jeb->wasted_size; | ||
| 194 | unchecked += jeb->unchecked_size; | ||
| 195 | } | ||
| 196 | list_for_each_entry(jeb, &c->dirty_list, list) { | ||
| 197 | nr_counted++; | ||
| 198 | free += jeb->free_size; | ||
| 199 | dirty += jeb->dirty_size; | ||
| 200 | used += jeb->used_size; | ||
| 201 | wasted += jeb->wasted_size; | ||
| 202 | unchecked += jeb->unchecked_size; | ||
| 203 | } | ||
| 204 | list_for_each_entry(jeb, &c->erasable_list, list) { | ||
| 205 | nr_counted++; | ||
| 206 | free += jeb->free_size; | ||
| 207 | dirty += jeb->dirty_size; | ||
| 208 | used += jeb->used_size; | ||
| 209 | wasted += jeb->wasted_size; | ||
| 210 | unchecked += jeb->unchecked_size; | ||
| 211 | } | ||
| 212 | list_for_each_entry(jeb, &c->erasable_pending_wbuf_list, list) { | ||
| 213 | nr_counted++; | ||
| 214 | free += jeb->free_size; | ||
| 215 | dirty += jeb->dirty_size; | ||
| 216 | used += jeb->used_size; | ||
| 217 | wasted += jeb->wasted_size; | ||
| 218 | unchecked += jeb->unchecked_size; | ||
| 219 | } | ||
| 220 | list_for_each_entry(jeb, &c->erase_pending_list, list) { | ||
| 221 | nr_counted++; | ||
| 222 | free += jeb->free_size; | ||
| 223 | dirty += jeb->dirty_size; | ||
| 224 | used += jeb->used_size; | ||
| 225 | wasted += jeb->wasted_size; | ||
| 226 | unchecked += jeb->unchecked_size; | ||
| 227 | } | ||
| 228 | list_for_each_entry(jeb, &c->free_list, list) { | ||
| 229 | nr_counted++; | ||
| 230 | free += jeb->free_size; | ||
| 231 | dirty += jeb->dirty_size; | ||
| 232 | used += jeb->used_size; | ||
| 233 | wasted += jeb->wasted_size; | ||
| 234 | unchecked += jeb->unchecked_size; | ||
| 235 | } | ||
| 236 | list_for_each_entry(jeb, &c->bad_used_list, list) { | ||
| 237 | nr_counted++; | ||
| 238 | free += jeb->free_size; | ||
| 239 | dirty += jeb->dirty_size; | ||
| 240 | used += jeb->used_size; | ||
| 241 | wasted += jeb->wasted_size; | ||
| 242 | unchecked += jeb->unchecked_size; | ||
| 243 | } | ||
| 244 | |||
| 245 | list_for_each_entry(jeb, &c->erasing_list, list) { | ||
| 246 | nr_counted++; | ||
| 247 | erasing += c->sector_size; | ||
| 248 | } | ||
| 249 | list_for_each_entry(jeb, &c->erase_checking_list, list) { | ||
| 250 | nr_counted++; | ||
| 251 | erasing += c->sector_size; | ||
| 252 | } | ||
| 253 | list_for_each_entry(jeb, &c->erase_complete_list, list) { | ||
| 254 | nr_counted++; | ||
| 255 | erasing += c->sector_size; | ||
| 256 | } | ||
| 257 | list_for_each_entry(jeb, &c->bad_list, list) { | ||
| 258 | nr_counted++; | ||
| 259 | bad += c->sector_size; | ||
| 260 | } | ||
| 261 | |||
| 262 | #define check(sz) \ | ||
| 263 | if (sz != c->sz##_size) { \ | ||
| 264 | printk(KERN_WARNING #sz "_size mismatch counted 0x%x, c->" #sz "_size 0x%x\n", \ | ||
| 265 | sz, c->sz##_size); \ | ||
| 266 | dump = 1; \ | ||
| 267 | } | ||
| 268 | check(free); | ||
| 269 | check(dirty); | ||
| 270 | check(used); | ||
| 271 | check(wasted); | ||
| 272 | check(unchecked); | ||
| 273 | check(bad); | ||
| 274 | check(erasing); | ||
| 275 | #undef check | ||
| 276 | |||
| 277 | if (nr_counted != c->nr_blocks) { | ||
| 278 | printk(KERN_WARNING "%s counted only 0x%x blocks of 0x%x. Where are the others?\n", | ||
| 279 | __func__, nr_counted, c->nr_blocks); | ||
| 280 | dump = 1; | ||
| 281 | } | ||
| 282 | |||
| 283 | if (dump) { | ||
| 284 | __jffs2_dbg_dump_block_lists_nolock(c); | ||
| 285 | BUG(); | ||
| 286 | } | ||
| 287 | } | ||
| 288 | |||
| 156 | /* | 289 | /* |
| 157 | * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'. | 290 | * Check the space accounting and node_ref list correctness for the JFFS2 erasable block 'jeb'. |
| 158 | */ | 291 | */ |
| @@ -229,6 +362,9 @@ __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c, | |||
| 229 | } | 362 | } |
| 230 | #endif | 363 | #endif |
| 231 | 364 | ||
| 365 | if (!(c->flags & (JFFS2_SB_FLAG_BUILDING|JFFS2_SB_FLAG_SCANNING))) | ||
| 366 | __jffs2_dbg_superblock_counts(c); | ||
| 367 | |||
| 232 | return; | 368 | return; |
| 233 | 369 | ||
| 234 | error: | 370 | error: |
| @@ -268,7 +404,10 @@ __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c, | |||
| 268 | 404 | ||
| 269 | printk(JFFS2_DBG); | 405 | printk(JFFS2_DBG); |
| 270 | for (ref = jeb->first_node; ; ref = ref_next(ref)) { | 406 | for (ref = jeb->first_node; ; ref = ref_next(ref)) { |
| 271 | printk("%#08x(%#x)", ref_offset(ref), ref->__totlen); | 407 | printk("%#08x", ref_offset(ref)); |
| 408 | #ifdef TEST_TOTLEN | ||
| 409 | printk("(%x)", ref->__totlen); | ||
| 410 | #endif | ||
| 272 | if (ref_next(ref)) | 411 | if (ref_next(ref)) |
| 273 | printk("->"); | 412 | printk("->"); |
| 274 | else | 413 | else |
| @@ -447,6 +586,21 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) | |||
| 447 | } | 586 | } |
| 448 | } | 587 | } |
| 449 | } | 588 | } |
| 589 | if (list_empty(&c->erase_checking_list)) { | ||
| 590 | printk(JFFS2_DBG "erase_checking_list: empty\n"); | ||
| 591 | } else { | ||
| 592 | struct list_head *this; | ||
| 593 | |||
| 594 | list_for_each(this, &c->erase_checking_list) { | ||
| 595 | struct jffs2_eraseblock *jeb = list_entry(this, struct jffs2_eraseblock, list); | ||
| 596 | |||
| 597 | if (!(jeb->used_size == 0 && jeb->dirty_size == 0 && jeb->wasted_size == 0)) { | ||
| 598 | printk(JFFS2_DBG "erase_checking_list: %#08x (used %#08x, dirty %#08x, wasted %#08x, unchecked %#08x, free %#08x)\n", | ||
| 599 | jeb->offset, jeb->used_size, jeb->dirty_size, jeb->wasted_size, | ||
| 600 | jeb->unchecked_size, jeb->free_size); | ||
| 601 | } | ||
| 602 | } | ||
| 603 | } | ||
| 450 | 604 | ||
| 451 | if (list_empty(&c->erase_pending_list)) { | 605 | if (list_empty(&c->erase_pending_list)) { |
| 452 | printk(JFFS2_DBG "erase_pending_list: empty\n"); | 606 | printk(JFFS2_DBG "erase_pending_list: empty\n"); |
| @@ -532,9 +686,9 @@ __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) | |||
| 532 | void | 686 | void |
| 533 | __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f) | 687 | __jffs2_dbg_dump_fragtree(struct jffs2_inode_info *f) |
| 534 | { | 688 | { |
| 535 | down(&f->sem); | 689 | mutex_lock(&f->sem); |
| 536 | jffs2_dbg_dump_fragtree_nolock(f); | 690 | jffs2_dbg_dump_fragtree_nolock(f); |
| 537 | up(&f->sem); | 691 | mutex_unlock(&f->sem); |
| 538 | } | 692 | } |
| 539 | 693 | ||
| 540 | void | 694 | void |
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 4130adabd76e..9645275023e6 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | 38 | ||
| 39 | #if CONFIG_JFFS2_FS_DEBUG > 1 | 39 | #if CONFIG_JFFS2_FS_DEBUG > 1 |
| 40 | #define JFFS2_DBG_FRAGTREE2_MESSAGES | 40 | #define JFFS2_DBG_FRAGTREE2_MESSAGES |
| 41 | #define JFFS2_DBG_READINODE2_MESSAGES | ||
| 41 | #define JFFS2_DBG_MEMALLOC_MESSAGES | 42 | #define JFFS2_DBG_MEMALLOC_MESSAGES |
| 42 | #endif | 43 | #endif |
| 43 | 44 | ||
| @@ -115,6 +116,11 @@ | |||
| 115 | #else | 116 | #else |
| 116 | #define dbg_readinode(fmt, ...) | 117 | #define dbg_readinode(fmt, ...) |
| 117 | #endif | 118 | #endif |
| 119 | #ifdef JFFS2_DBG_READINODE2_MESSAGES | ||
| 120 | #define dbg_readinode2(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) | ||
| 121 | #else | ||
| 122 | #define dbg_readinode2(fmt, ...) | ||
| 123 | #endif | ||
| 118 | 124 | ||
| 119 | /* Fragtree build debugging messages */ | 125 | /* Fragtree build debugging messages */ |
| 120 | #ifdef JFFS2_DBG_FRAGTREE_MESSAGES | 126 | #ifdef JFFS2_DBG_FRAGTREE_MESSAGES |
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index f948f7e6ec82..c63e7a96af0d 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
| @@ -86,7 +86,7 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, | |||
| 86 | dir_f = JFFS2_INODE_INFO(dir_i); | 86 | dir_f = JFFS2_INODE_INFO(dir_i); |
| 87 | c = JFFS2_SB_INFO(dir_i->i_sb); | 87 | c = JFFS2_SB_INFO(dir_i->i_sb); |
| 88 | 88 | ||
| 89 | down(&dir_f->sem); | 89 | mutex_lock(&dir_f->sem); |
| 90 | 90 | ||
| 91 | /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */ | 91 | /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */ |
| 92 | for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) { | 92 | for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) { |
| @@ -99,7 +99,7 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, | |||
| 99 | } | 99 | } |
| 100 | if (fd) | 100 | if (fd) |
| 101 | ino = fd->ino; | 101 | ino = fd->ino; |
| 102 | up(&dir_f->sem); | 102 | mutex_unlock(&dir_f->sem); |
| 103 | if (ino) { | 103 | if (ino) { |
| 104 | inode = jffs2_iget(dir_i->i_sb, ino); | 104 | inode = jffs2_iget(dir_i->i_sb, ino); |
| 105 | if (IS_ERR(inode)) { | 105 | if (IS_ERR(inode)) { |
| @@ -146,7 +146,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | curofs=1; | 148 | curofs=1; |
| 149 | down(&f->sem); | 149 | mutex_lock(&f->sem); |
| 150 | for (fd = f->dents; fd; fd = fd->next) { | 150 | for (fd = f->dents; fd; fd = fd->next) { |
| 151 | 151 | ||
| 152 | curofs++; | 152 | curofs++; |
| @@ -166,7 +166,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) | |||
| 166 | break; | 166 | break; |
| 167 | offset++; | 167 | offset++; |
| 168 | } | 168 | } |
| 169 | up(&f->sem); | 169 | mutex_unlock(&f->sem); |
| 170 | out: | 170 | out: |
| 171 | filp->f_pos = offset; | 171 | filp->f_pos = offset; |
| 172 | return 0; | 172 | return 0; |
| @@ -275,9 +275,9 @@ static int jffs2_link (struct dentry *old_dentry, struct inode *dir_i, struct de | |||
| 275 | ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now); | 275 | ret = jffs2_do_link(c, dir_f, f->inocache->ino, type, dentry->d_name.name, dentry->d_name.len, now); |
| 276 | 276 | ||
| 277 | if (!ret) { | 277 | if (!ret) { |
| 278 | down(&f->sem); | 278 | mutex_lock(&f->sem); |
| 279 | old_dentry->d_inode->i_nlink = ++f->inocache->nlink; | 279 | old_dentry->d_inode->i_nlink = ++f->inocache->nlink; |
| 280 | up(&f->sem); | 280 | mutex_unlock(&f->sem); |
| 281 | d_instantiate(dentry, old_dentry->d_inode); | 281 | d_instantiate(dentry, old_dentry->d_inode); |
| 282 | dir_i->i_mtime = dir_i->i_ctime = ITIME(now); | 282 | dir_i->i_mtime = dir_i->i_ctime = ITIME(now); |
| 283 | atomic_inc(&old_dentry->d_inode->i_count); | 283 | atomic_inc(&old_dentry->d_inode->i_count); |
| @@ -351,7 +351,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
| 351 | 351 | ||
| 352 | if (IS_ERR(fn)) { | 352 | if (IS_ERR(fn)) { |
| 353 | /* Eeek. Wave bye bye */ | 353 | /* Eeek. Wave bye bye */ |
| 354 | up(&f->sem); | 354 | mutex_unlock(&f->sem); |
| 355 | jffs2_complete_reservation(c); | 355 | jffs2_complete_reservation(c); |
| 356 | jffs2_clear_inode(inode); | 356 | jffs2_clear_inode(inode); |
| 357 | return PTR_ERR(fn); | 357 | return PTR_ERR(fn); |
| @@ -361,7 +361,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
| 361 | f->target = kmalloc(targetlen + 1, GFP_KERNEL); | 361 | f->target = kmalloc(targetlen + 1, GFP_KERNEL); |
| 362 | if (!f->target) { | 362 | if (!f->target) { |
| 363 | printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); | 363 | printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); |
| 364 | up(&f->sem); | 364 | mutex_unlock(&f->sem); |
| 365 | jffs2_complete_reservation(c); | 365 | jffs2_complete_reservation(c); |
| 366 | jffs2_clear_inode(inode); | 366 | jffs2_clear_inode(inode); |
| 367 | return -ENOMEM; | 367 | return -ENOMEM; |
| @@ -374,7 +374,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
| 374 | obsoleted by the first data write | 374 | obsoleted by the first data write |
| 375 | */ | 375 | */ |
| 376 | f->metadata = fn; | 376 | f->metadata = fn; |
| 377 | up(&f->sem); | 377 | mutex_unlock(&f->sem); |
| 378 | 378 | ||
| 379 | jffs2_complete_reservation(c); | 379 | jffs2_complete_reservation(c); |
| 380 | 380 | ||
| @@ -406,7 +406,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
| 406 | } | 406 | } |
| 407 | 407 | ||
| 408 | dir_f = JFFS2_INODE_INFO(dir_i); | 408 | dir_f = JFFS2_INODE_INFO(dir_i); |
| 409 | down(&dir_f->sem); | 409 | mutex_lock(&dir_f->sem); |
| 410 | 410 | ||
| 411 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 411 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
| 412 | rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); | 412 | rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); |
| @@ -429,7 +429,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
| 429 | as if it were the final unlink() */ | 429 | as if it were the final unlink() */ |
| 430 | jffs2_complete_reservation(c); | 430 | jffs2_complete_reservation(c); |
| 431 | jffs2_free_raw_dirent(rd); | 431 | jffs2_free_raw_dirent(rd); |
| 432 | up(&dir_f->sem); | 432 | mutex_unlock(&dir_f->sem); |
| 433 | jffs2_clear_inode(inode); | 433 | jffs2_clear_inode(inode); |
| 434 | return PTR_ERR(fd); | 434 | return PTR_ERR(fd); |
| 435 | } | 435 | } |
| @@ -442,7 +442,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
| 442 | one if necessary. */ | 442 | one if necessary. */ |
| 443 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); | 443 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); |
| 444 | 444 | ||
| 445 | up(&dir_f->sem); | 445 | mutex_unlock(&dir_f->sem); |
| 446 | jffs2_complete_reservation(c); | 446 | jffs2_complete_reservation(c); |
| 447 | 447 | ||
| 448 | d_instantiate(dentry, inode); | 448 | d_instantiate(dentry, inode); |
| @@ -507,7 +507,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
| 507 | 507 | ||
| 508 | if (IS_ERR(fn)) { | 508 | if (IS_ERR(fn)) { |
| 509 | /* Eeek. Wave bye bye */ | 509 | /* Eeek. Wave bye bye */ |
| 510 | up(&f->sem); | 510 | mutex_unlock(&f->sem); |
| 511 | jffs2_complete_reservation(c); | 511 | jffs2_complete_reservation(c); |
| 512 | jffs2_clear_inode(inode); | 512 | jffs2_clear_inode(inode); |
| 513 | return PTR_ERR(fn); | 513 | return PTR_ERR(fn); |
| @@ -516,7 +516,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
| 516 | obsoleted by the first data write | 516 | obsoleted by the first data write |
| 517 | */ | 517 | */ |
| 518 | f->metadata = fn; | 518 | f->metadata = fn; |
| 519 | up(&f->sem); | 519 | mutex_unlock(&f->sem); |
| 520 | 520 | ||
| 521 | jffs2_complete_reservation(c); | 521 | jffs2_complete_reservation(c); |
| 522 | 522 | ||
| @@ -548,7 +548,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
| 548 | } | 548 | } |
| 549 | 549 | ||
| 550 | dir_f = JFFS2_INODE_INFO(dir_i); | 550 | dir_f = JFFS2_INODE_INFO(dir_i); |
| 551 | down(&dir_f->sem); | 551 | mutex_lock(&dir_f->sem); |
| 552 | 552 | ||
| 553 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 553 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
| 554 | rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); | 554 | rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); |
| @@ -571,7 +571,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
| 571 | as if it were the final unlink() */ | 571 | as if it were the final unlink() */ |
| 572 | jffs2_complete_reservation(c); | 572 | jffs2_complete_reservation(c); |
| 573 | jffs2_free_raw_dirent(rd); | 573 | jffs2_free_raw_dirent(rd); |
| 574 | up(&dir_f->sem); | 574 | mutex_unlock(&dir_f->sem); |
| 575 | jffs2_clear_inode(inode); | 575 | jffs2_clear_inode(inode); |
| 576 | return PTR_ERR(fd); | 576 | return PTR_ERR(fd); |
| 577 | } | 577 | } |
| @@ -585,7 +585,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
| 585 | one if necessary. */ | 585 | one if necessary. */ |
| 586 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); | 586 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); |
| 587 | 587 | ||
| 588 | up(&dir_f->sem); | 588 | mutex_unlock(&dir_f->sem); |
| 589 | jffs2_complete_reservation(c); | 589 | jffs2_complete_reservation(c); |
| 590 | 590 | ||
| 591 | d_instantiate(dentry, inode); | 591 | d_instantiate(dentry, inode); |
| @@ -673,7 +673,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
| 673 | 673 | ||
| 674 | if (IS_ERR(fn)) { | 674 | if (IS_ERR(fn)) { |
| 675 | /* Eeek. Wave bye bye */ | 675 | /* Eeek. Wave bye bye */ |
| 676 | up(&f->sem); | 676 | mutex_unlock(&f->sem); |
| 677 | jffs2_complete_reservation(c); | 677 | jffs2_complete_reservation(c); |
| 678 | jffs2_clear_inode(inode); | 678 | jffs2_clear_inode(inode); |
| 679 | return PTR_ERR(fn); | 679 | return PTR_ERR(fn); |
| @@ -682,7 +682,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
| 682 | obsoleted by the first data write | 682 | obsoleted by the first data write |
| 683 | */ | 683 | */ |
| 684 | f->metadata = fn; | 684 | f->metadata = fn; |
| 685 | up(&f->sem); | 685 | mutex_unlock(&f->sem); |
| 686 | 686 | ||
| 687 | jffs2_complete_reservation(c); | 687 | jffs2_complete_reservation(c); |
| 688 | 688 | ||
| @@ -714,7 +714,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
| 714 | } | 714 | } |
| 715 | 715 | ||
| 716 | dir_f = JFFS2_INODE_INFO(dir_i); | 716 | dir_f = JFFS2_INODE_INFO(dir_i); |
| 717 | down(&dir_f->sem); | 717 | mutex_lock(&dir_f->sem); |
| 718 | 718 | ||
| 719 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 719 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
| 720 | rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); | 720 | rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); |
| @@ -740,7 +740,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
| 740 | as if it were the final unlink() */ | 740 | as if it were the final unlink() */ |
| 741 | jffs2_complete_reservation(c); | 741 | jffs2_complete_reservation(c); |
| 742 | jffs2_free_raw_dirent(rd); | 742 | jffs2_free_raw_dirent(rd); |
| 743 | up(&dir_f->sem); | 743 | mutex_unlock(&dir_f->sem); |
| 744 | jffs2_clear_inode(inode); | 744 | jffs2_clear_inode(inode); |
| 745 | return PTR_ERR(fd); | 745 | return PTR_ERR(fd); |
| 746 | } | 746 | } |
| @@ -753,7 +753,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
| 753 | one if necessary. */ | 753 | one if necessary. */ |
| 754 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); | 754 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); |
| 755 | 755 | ||
| 756 | up(&dir_f->sem); | 756 | mutex_unlock(&dir_f->sem); |
| 757 | jffs2_complete_reservation(c); | 757 | jffs2_complete_reservation(c); |
| 758 | 758 | ||
| 759 | d_instantiate(dentry, inode); | 759 | d_instantiate(dentry, inode); |
| @@ -780,14 +780,14 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | |||
| 780 | if (S_ISDIR(new_dentry->d_inode->i_mode)) { | 780 | if (S_ISDIR(new_dentry->d_inode->i_mode)) { |
| 781 | struct jffs2_full_dirent *fd; | 781 | struct jffs2_full_dirent *fd; |
| 782 | 782 | ||
| 783 | down(&victim_f->sem); | 783 | mutex_lock(&victim_f->sem); |
| 784 | for (fd = victim_f->dents; fd; fd = fd->next) { | 784 | for (fd = victim_f->dents; fd; fd = fd->next) { |
| 785 | if (fd->ino) { | 785 | if (fd->ino) { |
| 786 | up(&victim_f->sem); | 786 | mutex_unlock(&victim_f->sem); |
| 787 | return -ENOTEMPTY; | 787 | return -ENOTEMPTY; |
| 788 | } | 788 | } |
| 789 | } | 789 | } |
| 790 | up(&victim_f->sem); | 790 | mutex_unlock(&victim_f->sem); |
| 791 | } | 791 | } |
| 792 | } | 792 | } |
| 793 | 793 | ||
| @@ -816,9 +816,9 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | |||
| 816 | /* Don't oops if the victim was a dirent pointing to an | 816 | /* Don't oops if the victim was a dirent pointing to an |
| 817 | inode which didn't exist. */ | 817 | inode which didn't exist. */ |
| 818 | if (victim_f->inocache) { | 818 | if (victim_f->inocache) { |
| 819 | down(&victim_f->sem); | 819 | mutex_lock(&victim_f->sem); |
| 820 | victim_f->inocache->nlink--; | 820 | victim_f->inocache->nlink--; |
| 821 | up(&victim_f->sem); | 821 | mutex_unlock(&victim_f->sem); |
| 822 | } | 822 | } |
| 823 | } | 823 | } |
| 824 | 824 | ||
| @@ -836,11 +836,11 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, | |||
| 836 | if (ret) { | 836 | if (ret) { |
| 837 | /* Oh shit. We really ought to make a single node which can do both atomically */ | 837 | /* Oh shit. We really ought to make a single node which can do both atomically */ |
| 838 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); | 838 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_dentry->d_inode); |
| 839 | down(&f->sem); | 839 | mutex_lock(&f->sem); |
| 840 | inc_nlink(old_dentry->d_inode); | 840 | inc_nlink(old_dentry->d_inode); |
| 841 | if (f->inocache) | 841 | if (f->inocache) |
| 842 | f->inocache->nlink++; | 842 | f->inocache->nlink++; |
| 843 | up(&f->sem); | 843 | mutex_unlock(&f->sem); |
| 844 | 844 | ||
| 845 | printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret); | 845 | printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret); |
| 846 | /* Might as well let the VFS know */ | 846 | /* Might as well let the VFS know */ |
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index a1db9180633f..25a640e566d3 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c | |||
| @@ -50,14 +50,14 @@ static void jffs2_erase_block(struct jffs2_sb_info *c, | |||
| 50 | instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL); | 50 | instr = kmalloc(sizeof(struct erase_info) + sizeof(struct erase_priv_struct), GFP_KERNEL); |
| 51 | if (!instr) { | 51 | if (!instr) { |
| 52 | printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n"); | 52 | printk(KERN_WARNING "kmalloc for struct erase_info in jffs2_erase_block failed. Refiling block for later\n"); |
| 53 | down(&c->erase_free_sem); | 53 | mutex_lock(&c->erase_free_sem); |
| 54 | spin_lock(&c->erase_completion_lock); | 54 | spin_lock(&c->erase_completion_lock); |
| 55 | list_move(&jeb->list, &c->erase_pending_list); | 55 | list_move(&jeb->list, &c->erase_pending_list); |
| 56 | c->erasing_size -= c->sector_size; | 56 | c->erasing_size -= c->sector_size; |
| 57 | c->dirty_size += c->sector_size; | 57 | c->dirty_size += c->sector_size; |
| 58 | jeb->dirty_size = c->sector_size; | 58 | jeb->dirty_size = c->sector_size; |
| 59 | spin_unlock(&c->erase_completion_lock); | 59 | spin_unlock(&c->erase_completion_lock); |
| 60 | up(&c->erase_free_sem); | 60 | mutex_unlock(&c->erase_free_sem); |
| 61 | return; | 61 | return; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| @@ -84,14 +84,14 @@ static void jffs2_erase_block(struct jffs2_sb_info *c, | |||
| 84 | if (ret == -ENOMEM || ret == -EAGAIN) { | 84 | if (ret == -ENOMEM || ret == -EAGAIN) { |
| 85 | /* Erase failed immediately. Refile it on the list */ | 85 | /* Erase failed immediately. Refile it on the list */ |
| 86 | D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret)); | 86 | D1(printk(KERN_DEBUG "Erase at 0x%08x failed: %d. Refiling on erase_pending_list\n", jeb->offset, ret)); |
| 87 | down(&c->erase_free_sem); | 87 | mutex_lock(&c->erase_free_sem); |
| 88 | spin_lock(&c->erase_completion_lock); | 88 | spin_lock(&c->erase_completion_lock); |
| 89 | list_move(&jeb->list, &c->erase_pending_list); | 89 | list_move(&jeb->list, &c->erase_pending_list); |
| 90 | c->erasing_size -= c->sector_size; | 90 | c->erasing_size -= c->sector_size; |
| 91 | c->dirty_size += c->sector_size; | 91 | c->dirty_size += c->sector_size; |
| 92 | jeb->dirty_size = c->sector_size; | 92 | jeb->dirty_size = c->sector_size; |
| 93 | spin_unlock(&c->erase_completion_lock); | 93 | spin_unlock(&c->erase_completion_lock); |
| 94 | up(&c->erase_free_sem); | 94 | mutex_unlock(&c->erase_free_sem); |
| 95 | return; | 95 | return; |
| 96 | } | 96 | } |
| 97 | 97 | ||
| @@ -107,7 +107,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) | |||
| 107 | { | 107 | { |
| 108 | struct jffs2_eraseblock *jeb; | 108 | struct jffs2_eraseblock *jeb; |
| 109 | 109 | ||
| 110 | down(&c->erase_free_sem); | 110 | mutex_lock(&c->erase_free_sem); |
| 111 | 111 | ||
| 112 | spin_lock(&c->erase_completion_lock); | 112 | spin_lock(&c->erase_completion_lock); |
| 113 | 113 | ||
| @@ -116,9 +116,9 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) | |||
| 116 | 116 | ||
| 117 | if (!list_empty(&c->erase_complete_list)) { | 117 | if (!list_empty(&c->erase_complete_list)) { |
| 118 | jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list); | 118 | jeb = list_entry(c->erase_complete_list.next, struct jffs2_eraseblock, list); |
| 119 | list_del(&jeb->list); | 119 | list_move(&jeb->list, &c->erase_checking_list); |
| 120 | spin_unlock(&c->erase_completion_lock); | 120 | spin_unlock(&c->erase_completion_lock); |
| 121 | up(&c->erase_free_sem); | 121 | mutex_unlock(&c->erase_free_sem); |
| 122 | jffs2_mark_erased_block(c, jeb); | 122 | jffs2_mark_erased_block(c, jeb); |
| 123 | 123 | ||
| 124 | if (!--count) { | 124 | if (!--count) { |
| @@ -139,7 +139,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) | |||
| 139 | jffs2_free_jeb_node_refs(c, jeb); | 139 | jffs2_free_jeb_node_refs(c, jeb); |
| 140 | list_add(&jeb->list, &c->erasing_list); | 140 | list_add(&jeb->list, &c->erasing_list); |
| 141 | spin_unlock(&c->erase_completion_lock); | 141 | spin_unlock(&c->erase_completion_lock); |
| 142 | up(&c->erase_free_sem); | 142 | mutex_unlock(&c->erase_free_sem); |
| 143 | 143 | ||
| 144 | jffs2_erase_block(c, jeb); | 144 | jffs2_erase_block(c, jeb); |
| 145 | 145 | ||
| @@ -149,12 +149,12 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) | |||
| 149 | 149 | ||
| 150 | /* Be nice */ | 150 | /* Be nice */ |
| 151 | yield(); | 151 | yield(); |
| 152 | down(&c->erase_free_sem); | 152 | mutex_lock(&c->erase_free_sem); |
| 153 | spin_lock(&c->erase_completion_lock); | 153 | spin_lock(&c->erase_completion_lock); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | spin_unlock(&c->erase_completion_lock); | 156 | spin_unlock(&c->erase_completion_lock); |
| 157 | up(&c->erase_free_sem); | 157 | mutex_unlock(&c->erase_free_sem); |
| 158 | done: | 158 | done: |
| 159 | D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n")); | 159 | D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n")); |
| 160 | } | 160 | } |
| @@ -162,11 +162,11 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) | |||
| 162 | static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) | 162 | static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) |
| 163 | { | 163 | { |
| 164 | D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset)); | 164 | D1(printk(KERN_DEBUG "Erase completed successfully at 0x%08x\n", jeb->offset)); |
| 165 | down(&c->erase_free_sem); | 165 | mutex_lock(&c->erase_free_sem); |
| 166 | spin_lock(&c->erase_completion_lock); | 166 | spin_lock(&c->erase_completion_lock); |
| 167 | list_move_tail(&jeb->list, &c->erase_complete_list); | 167 | list_move_tail(&jeb->list, &c->erase_complete_list); |
| 168 | spin_unlock(&c->erase_completion_lock); | 168 | spin_unlock(&c->erase_completion_lock); |
| 169 | up(&c->erase_free_sem); | 169 | mutex_unlock(&c->erase_free_sem); |
| 170 | /* Ensure that kupdated calls us again to mark them clean */ | 170 | /* Ensure that kupdated calls us again to mark them clean */ |
| 171 | jffs2_erase_pending_trigger(c); | 171 | jffs2_erase_pending_trigger(c); |
| 172 | } | 172 | } |
| @@ -180,26 +180,26 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
| 180 | failed too many times. */ | 180 | failed too many times. */ |
| 181 | if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) { | 181 | if (!jffs2_write_nand_badblock(c, jeb, bad_offset)) { |
| 182 | /* We'd like to give this block another try. */ | 182 | /* We'd like to give this block another try. */ |
| 183 | down(&c->erase_free_sem); | 183 | mutex_lock(&c->erase_free_sem); |
| 184 | spin_lock(&c->erase_completion_lock); | 184 | spin_lock(&c->erase_completion_lock); |
| 185 | list_move(&jeb->list, &c->erase_pending_list); | 185 | list_move(&jeb->list, &c->erase_pending_list); |
| 186 | c->erasing_size -= c->sector_size; | 186 | c->erasing_size -= c->sector_size; |
| 187 | c->dirty_size += c->sector_size; | 187 | c->dirty_size += c->sector_size; |
| 188 | jeb->dirty_size = c->sector_size; | 188 | jeb->dirty_size = c->sector_size; |
| 189 | spin_unlock(&c->erase_completion_lock); | 189 | spin_unlock(&c->erase_completion_lock); |
| 190 | up(&c->erase_free_sem); | 190 | mutex_unlock(&c->erase_free_sem); |
| 191 | return; | 191 | return; |
| 192 | } | 192 | } |
| 193 | } | 193 | } |
| 194 | 194 | ||
| 195 | down(&c->erase_free_sem); | 195 | mutex_lock(&c->erase_free_sem); |
| 196 | spin_lock(&c->erase_completion_lock); | 196 | spin_lock(&c->erase_completion_lock); |
| 197 | c->erasing_size -= c->sector_size; | 197 | c->erasing_size -= c->sector_size; |
| 198 | c->bad_size += c->sector_size; | 198 | c->bad_size += c->sector_size; |
| 199 | list_move(&jeb->list, &c->bad_list); | 199 | list_move(&jeb->list, &c->bad_list); |
| 200 | c->nr_erasing_blocks--; | 200 | c->nr_erasing_blocks--; |
| 201 | spin_unlock(&c->erase_completion_lock); | 201 | spin_unlock(&c->erase_completion_lock); |
| 202 | up(&c->erase_free_sem); | 202 | mutex_unlock(&c->erase_free_sem); |
| 203 | wake_up(&c->erase_wait); | 203 | wake_up(&c->erase_wait); |
| 204 | } | 204 | } |
| 205 | 205 | ||
| @@ -350,9 +350,11 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl | |||
| 350 | break; | 350 | break; |
| 351 | } while(--retlen); | 351 | } while(--retlen); |
| 352 | c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size); | 352 | c->mtd->unpoint(c->mtd, ebuf, jeb->offset, c->sector_size); |
| 353 | if (retlen) | 353 | if (retlen) { |
| 354 | printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08tx\n", | 354 | printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08tx\n", |
| 355 | *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf)); | 355 | *wordebuf, jeb->offset + c->sector_size-retlen*sizeof(*wordebuf)); |
| 356 | return -EIO; | ||
| 357 | } | ||
| 356 | return 0; | 358 | return 0; |
| 357 | } | 359 | } |
| 358 | do_flash_read: | 360 | do_flash_read: |
| @@ -373,10 +375,12 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl | |||
| 373 | ret = c->mtd->read(c->mtd, ofs, readlen, &retlen, ebuf); | 375 | ret = c->mtd->read(c->mtd, ofs, readlen, &retlen, ebuf); |
| 374 | if (ret) { | 376 | if (ret) { |
| 375 | printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret); | 377 | printk(KERN_WARNING "Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n", ofs, ret); |
| 378 | ret = -EIO; | ||
| 376 | goto fail; | 379 | goto fail; |
| 377 | } | 380 | } |
| 378 | if (retlen != readlen) { | 381 | if (retlen != readlen) { |
| 379 | printk(KERN_WARNING "Short read from newly-erased block at 0x%08x. Wanted %d, got %zd\n", ofs, readlen, retlen); | 382 | printk(KERN_WARNING "Short read from newly-erased block at 0x%08x. Wanted %d, got %zd\n", ofs, readlen, retlen); |
| 383 | ret = -EIO; | ||
| 380 | goto fail; | 384 | goto fail; |
| 381 | } | 385 | } |
| 382 | for (i=0; i<readlen; i += sizeof(unsigned long)) { | 386 | for (i=0; i<readlen; i += sizeof(unsigned long)) { |
| @@ -385,6 +389,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl | |||
| 385 | if (*datum + 1) { | 389 | if (*datum + 1) { |
| 386 | *bad_offset += i; | 390 | *bad_offset += i; |
| 387 | printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n", *datum, *bad_offset); | 391 | printk(KERN_WARNING "Newly-erased block contained word 0x%lx at offset 0x%08x\n", *datum, *bad_offset); |
| 392 | ret = -EIO; | ||
| 388 | goto fail; | 393 | goto fail; |
| 389 | } | 394 | } |
| 390 | } | 395 | } |
| @@ -419,9 +424,6 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb | |||
| 419 | if (jffs2_write_nand_cleanmarker(c, jeb)) | 424 | if (jffs2_write_nand_cleanmarker(c, jeb)) |
| 420 | goto filebad; | 425 | goto filebad; |
| 421 | } | 426 | } |
| 422 | |||
| 423 | /* Everything else got zeroed before the erase */ | ||
| 424 | jeb->free_size = c->sector_size; | ||
| 425 | } else { | 427 | } else { |
| 426 | 428 | ||
| 427 | struct kvec vecs[1]; | 429 | struct kvec vecs[1]; |
| @@ -449,48 +451,50 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb | |||
| 449 | 451 | ||
| 450 | goto filebad; | 452 | goto filebad; |
| 451 | } | 453 | } |
| 452 | |||
| 453 | /* Everything else got zeroed before the erase */ | ||
| 454 | jeb->free_size = c->sector_size; | ||
| 455 | /* FIXME Special case for cleanmarker in empty block */ | ||
| 456 | jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL); | ||
| 457 | } | 454 | } |
| 455 | /* Everything else got zeroed before the erase */ | ||
| 456 | jeb->free_size = c->sector_size; | ||
| 458 | 457 | ||
| 459 | down(&c->erase_free_sem); | 458 | mutex_lock(&c->erase_free_sem); |
| 460 | spin_lock(&c->erase_completion_lock); | 459 | spin_lock(&c->erase_completion_lock); |
| 460 | |||
| 461 | c->erasing_size -= c->sector_size; | 461 | c->erasing_size -= c->sector_size; |
| 462 | c->free_size += jeb->free_size; | 462 | c->free_size += c->sector_size; |
| 463 | c->used_size += jeb->used_size; | ||
| 464 | 463 | ||
| 465 | jffs2_dbg_acct_sanity_check_nolock(c,jeb); | 464 | /* Account for cleanmarker now, if it's in-band */ |
| 466 | jffs2_dbg_acct_paranoia_check_nolock(c, jeb); | 465 | if (c->cleanmarker_size && !jffs2_cleanmarker_oob(c)) |
| 466 | jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL); | ||
| 467 | 467 | ||
| 468 | list_add_tail(&jeb->list, &c->free_list); | 468 | list_move_tail(&jeb->list, &c->free_list); |
| 469 | c->nr_erasing_blocks--; | 469 | c->nr_erasing_blocks--; |
| 470 | c->nr_free_blocks++; | 470 | c->nr_free_blocks++; |
| 471 | |||
| 472 | jffs2_dbg_acct_sanity_check_nolock(c, jeb); | ||
| 473 | jffs2_dbg_acct_paranoia_check_nolock(c, jeb); | ||
| 474 | |||
| 471 | spin_unlock(&c->erase_completion_lock); | 475 | spin_unlock(&c->erase_completion_lock); |
| 472 | up(&c->erase_free_sem); | 476 | mutex_unlock(&c->erase_free_sem); |
| 473 | wake_up(&c->erase_wait); | 477 | wake_up(&c->erase_wait); |
| 474 | return; | 478 | return; |
| 475 | 479 | ||
| 476 | filebad: | 480 | filebad: |
| 477 | down(&c->erase_free_sem); | 481 | mutex_lock(&c->erase_free_sem); |
| 478 | spin_lock(&c->erase_completion_lock); | 482 | spin_lock(&c->erase_completion_lock); |
| 479 | /* Stick it on a list (any list) so erase_failed can take it | 483 | /* Stick it on a list (any list) so erase_failed can take it |
| 480 | right off again. Silly, but shouldn't happen often. */ | 484 | right off again. Silly, but shouldn't happen often. */ |
| 481 | list_add(&jeb->list, &c->erasing_list); | 485 | list_move(&jeb->list, &c->erasing_list); |
| 482 | spin_unlock(&c->erase_completion_lock); | 486 | spin_unlock(&c->erase_completion_lock); |
| 483 | up(&c->erase_free_sem); | 487 | mutex_unlock(&c->erase_free_sem); |
| 484 | jffs2_erase_failed(c, jeb, bad_offset); | 488 | jffs2_erase_failed(c, jeb, bad_offset); |
| 485 | return; | 489 | return; |
| 486 | 490 | ||
| 487 | refile: | 491 | refile: |
| 488 | /* Stick it back on the list from whence it came and come back later */ | 492 | /* Stick it back on the list from whence it came and come back later */ |
| 489 | jffs2_erase_pending_trigger(c); | 493 | jffs2_erase_pending_trigger(c); |
| 490 | down(&c->erase_free_sem); | 494 | mutex_lock(&c->erase_free_sem); |
| 491 | spin_lock(&c->erase_completion_lock); | 495 | spin_lock(&c->erase_completion_lock); |
| 492 | list_add(&jeb->list, &c->erase_complete_list); | 496 | list_move(&jeb->list, &c->erase_complete_list); |
| 493 | spin_unlock(&c->erase_completion_lock); | 497 | spin_unlock(&c->erase_completion_lock); |
| 494 | up(&c->erase_free_sem); | 498 | mutex_unlock(&c->erase_free_sem); |
| 495 | return; | 499 | return; |
| 496 | } | 500 | } |
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index dcc2734e0b5d..5e920343b2c5 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c | |||
| @@ -115,9 +115,9 @@ static int jffs2_readpage (struct file *filp, struct page *pg) | |||
| 115 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host); | 115 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host); |
| 116 | int ret; | 116 | int ret; |
| 117 | 117 | ||
| 118 | down(&f->sem); | 118 | mutex_lock(&f->sem); |
| 119 | ret = jffs2_do_readpage_unlock(pg->mapping->host, pg); | 119 | ret = jffs2_do_readpage_unlock(pg->mapping->host, pg); |
| 120 | up(&f->sem); | 120 | mutex_unlock(&f->sem); |
| 121 | return ret; | 121 | return ret; |
| 122 | } | 122 | } |
| 123 | 123 | ||
| @@ -154,7 +154,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, | |||
| 154 | if (ret) | 154 | if (ret) |
| 155 | goto out_page; | 155 | goto out_page; |
| 156 | 156 | ||
| 157 | down(&f->sem); | 157 | mutex_lock(&f->sem); |
| 158 | memset(&ri, 0, sizeof(ri)); | 158 | memset(&ri, 0, sizeof(ri)); |
| 159 | 159 | ||
| 160 | ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 160 | ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
| @@ -181,7 +181,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, | |||
| 181 | if (IS_ERR(fn)) { | 181 | if (IS_ERR(fn)) { |
| 182 | ret = PTR_ERR(fn); | 182 | ret = PTR_ERR(fn); |
| 183 | jffs2_complete_reservation(c); | 183 | jffs2_complete_reservation(c); |
| 184 | up(&f->sem); | 184 | mutex_unlock(&f->sem); |
| 185 | goto out_page; | 185 | goto out_page; |
| 186 | } | 186 | } |
| 187 | ret = jffs2_add_full_dnode_to_inode(c, f, fn); | 187 | ret = jffs2_add_full_dnode_to_inode(c, f, fn); |
| @@ -195,12 +195,12 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, | |||
| 195 | jffs2_mark_node_obsolete(c, fn->raw); | 195 | jffs2_mark_node_obsolete(c, fn->raw); |
| 196 | jffs2_free_full_dnode(fn); | 196 | jffs2_free_full_dnode(fn); |
| 197 | jffs2_complete_reservation(c); | 197 | jffs2_complete_reservation(c); |
| 198 | up(&f->sem); | 198 | mutex_unlock(&f->sem); |
| 199 | goto out_page; | 199 | goto out_page; |
| 200 | } | 200 | } |
| 201 | jffs2_complete_reservation(c); | 201 | jffs2_complete_reservation(c); |
| 202 | inode->i_size = pageofs; | 202 | inode->i_size = pageofs; |
| 203 | up(&f->sem); | 203 | mutex_unlock(&f->sem); |
| 204 | } | 204 | } |
| 205 | 205 | ||
| 206 | /* | 206 | /* |
| @@ -209,9 +209,9 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, | |||
| 209 | * case of a short-copy. | 209 | * case of a short-copy. |
| 210 | */ | 210 | */ |
| 211 | if (!PageUptodate(pg)) { | 211 | if (!PageUptodate(pg)) { |
| 212 | down(&f->sem); | 212 | mutex_lock(&f->sem); |
| 213 | ret = jffs2_do_readpage_nolock(inode, pg); | 213 | ret = jffs2_do_readpage_nolock(inode, pg); |
| 214 | up(&f->sem); | 214 | mutex_unlock(&f->sem); |
| 215 | if (ret) | 215 | if (ret) |
| 216 | goto out_page; | 216 | goto out_page; |
| 217 | } | 217 | } |
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index e26ea78c7892..3eb1c84b0a33 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
| @@ -36,6 +36,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) | |||
| 36 | unsigned int ivalid; | 36 | unsigned int ivalid; |
| 37 | uint32_t alloclen; | 37 | uint32_t alloclen; |
| 38 | int ret; | 38 | int ret; |
| 39 | int alloc_type = ALLOC_NORMAL; | ||
| 39 | 40 | ||
| 40 | D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); | 41 | D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); |
| 41 | 42 | ||
| @@ -50,20 +51,20 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) | |||
| 50 | mdata = (char *)&dev; | 51 | mdata = (char *)&dev; |
| 51 | D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen)); | 52 | D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen)); |
| 52 | } else if (S_ISLNK(inode->i_mode)) { | 53 | } else if (S_ISLNK(inode->i_mode)) { |
| 53 | down(&f->sem); | 54 | mutex_lock(&f->sem); |
| 54 | mdatalen = f->metadata->size; | 55 | mdatalen = f->metadata->size; |
| 55 | mdata = kmalloc(f->metadata->size, GFP_USER); | 56 | mdata = kmalloc(f->metadata->size, GFP_USER); |
| 56 | if (!mdata) { | 57 | if (!mdata) { |
| 57 | up(&f->sem); | 58 | mutex_unlock(&f->sem); |
| 58 | return -ENOMEM; | 59 | return -ENOMEM; |
| 59 | } | 60 | } |
| 60 | ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen); | 61 | ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen); |
| 61 | if (ret) { | 62 | if (ret) { |
| 62 | up(&f->sem); | 63 | mutex_unlock(&f->sem); |
| 63 | kfree(mdata); | 64 | kfree(mdata); |
| 64 | return ret; | 65 | return ret; |
| 65 | } | 66 | } |
| 66 | up(&f->sem); | 67 | mutex_unlock(&f->sem); |
| 67 | D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen)); | 68 | D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen)); |
| 68 | } | 69 | } |
| 69 | 70 | ||
| @@ -82,7 +83,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) | |||
| 82 | kfree(mdata); | 83 | kfree(mdata); |
| 83 | return ret; | 84 | return ret; |
| 84 | } | 85 | } |
| 85 | down(&f->sem); | 86 | mutex_lock(&f->sem); |
| 86 | ivalid = iattr->ia_valid; | 87 | ivalid = iattr->ia_valid; |
| 87 | 88 | ||
| 88 | ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 89 | ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
| @@ -115,6 +116,10 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) | |||
| 115 | ri->compr = JFFS2_COMPR_ZERO; | 116 | ri->compr = JFFS2_COMPR_ZERO; |
| 116 | ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size); | 117 | ri->dsize = cpu_to_je32(iattr->ia_size - inode->i_size); |
| 117 | ri->offset = cpu_to_je32(inode->i_size); | 118 | ri->offset = cpu_to_je32(inode->i_size); |
| 119 | } else if (ivalid & ATTR_SIZE && !iattr->ia_size) { | ||
| 120 | /* For truncate-to-zero, treat it as deletion because | ||
| 121 | it'll always be obsoleting all previous nodes */ | ||
| 122 | alloc_type = ALLOC_DELETION; | ||
| 118 | } | 123 | } |
| 119 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); | 124 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
| 120 | if (mdatalen) | 125 | if (mdatalen) |
| @@ -122,14 +127,14 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) | |||
| 122 | else | 127 | else |
| 123 | ri->data_crc = cpu_to_je32(0); | 128 | ri->data_crc = cpu_to_je32(0); |
| 124 | 129 | ||
| 125 | new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, ALLOC_NORMAL); | 130 | new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, alloc_type); |
| 126 | if (S_ISLNK(inode->i_mode)) | 131 | if (S_ISLNK(inode->i_mode)) |
| 127 | kfree(mdata); | 132 | kfree(mdata); |
| 128 | 133 | ||
| 129 | if (IS_ERR(new_metadata)) { | 134 | if (IS_ERR(new_metadata)) { |
| 130 | jffs2_complete_reservation(c); | 135 | jffs2_complete_reservation(c); |
| 131 | jffs2_free_raw_inode(ri); | 136 | jffs2_free_raw_inode(ri); |
| 132 | up(&f->sem); | 137 | mutex_unlock(&f->sem); |
| 133 | return PTR_ERR(new_metadata); | 138 | return PTR_ERR(new_metadata); |
| 134 | } | 139 | } |
| 135 | /* It worked. Update the inode */ | 140 | /* It worked. Update the inode */ |
| @@ -149,6 +154,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) | |||
| 149 | if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { | 154 | if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { |
| 150 | jffs2_add_full_dnode_to_inode(c, f, new_metadata); | 155 | jffs2_add_full_dnode_to_inode(c, f, new_metadata); |
| 151 | inode->i_size = iattr->ia_size; | 156 | inode->i_size = iattr->ia_size; |
| 157 | inode->i_blocks = (inode->i_size + 511) >> 9; | ||
| 152 | f->metadata = NULL; | 158 | f->metadata = NULL; |
| 153 | } else { | 159 | } else { |
| 154 | f->metadata = new_metadata; | 160 | f->metadata = new_metadata; |
| @@ -159,7 +165,7 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) | |||
| 159 | } | 165 | } |
| 160 | jffs2_free_raw_inode(ri); | 166 | jffs2_free_raw_inode(ri); |
| 161 | 167 | ||
| 162 | up(&f->sem); | 168 | mutex_unlock(&f->sem); |
| 163 | jffs2_complete_reservation(c); | 169 | jffs2_complete_reservation(c); |
| 164 | 170 | ||
| 165 | /* We have to do the vmtruncate() without f->sem held, since | 171 | /* We have to do the vmtruncate() without f->sem held, since |
| @@ -167,8 +173,10 @@ int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) | |||
| 167 | We are protected from a simultaneous write() extending i_size | 173 | We are protected from a simultaneous write() extending i_size |
| 168 | back past iattr->ia_size, because do_truncate() holds the | 174 | back past iattr->ia_size, because do_truncate() holds the |
| 169 | generic inode semaphore. */ | 175 | generic inode semaphore. */ |
| 170 | if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) | 176 | if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) { |
| 171 | vmtruncate(inode, iattr->ia_size); | 177 | vmtruncate(inode, iattr->ia_size); |
| 178 | inode->i_blocks = (inode->i_size + 511) >> 9; | ||
| 179 | } | ||
| 172 | 180 | ||
| 173 | return 0; | 181 | return 0; |
| 174 | } | 182 | } |
| @@ -248,12 +256,12 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino) | |||
| 248 | c = JFFS2_SB_INFO(inode->i_sb); | 256 | c = JFFS2_SB_INFO(inode->i_sb); |
| 249 | 257 | ||
| 250 | jffs2_init_inode_info(f); | 258 | jffs2_init_inode_info(f); |
| 251 | down(&f->sem); | 259 | mutex_lock(&f->sem); |
| 252 | 260 | ||
| 253 | ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); | 261 | ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); |
| 254 | 262 | ||
| 255 | if (ret) { | 263 | if (ret) { |
| 256 | up(&f->sem); | 264 | mutex_unlock(&f->sem); |
| 257 | iget_failed(inode); | 265 | iget_failed(inode); |
| 258 | return ERR_PTR(ret); | 266 | return ERR_PTR(ret); |
| 259 | } | 267 | } |
| @@ -330,7 +338,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino) | |||
| 330 | printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu\n", inode->i_mode, (unsigned long)inode->i_ino); | 338 | printk(KERN_WARNING "jffs2_read_inode(): Bogus imode %o for ino %lu\n", inode->i_mode, (unsigned long)inode->i_ino); |
| 331 | } | 339 | } |
| 332 | 340 | ||
| 333 | up(&f->sem); | 341 | mutex_unlock(&f->sem); |
| 334 | 342 | ||
| 335 | D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n")); | 343 | D1(printk(KERN_DEBUG "jffs2_read_inode() returning\n")); |
| 336 | unlock_new_inode(inode); | 344 | unlock_new_inode(inode); |
| @@ -339,7 +347,7 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino) | |||
| 339 | error_io: | 347 | error_io: |
| 340 | ret = -EIO; | 348 | ret = -EIO; |
| 341 | error: | 349 | error: |
| 342 | up(&f->sem); | 350 | mutex_unlock(&f->sem); |
| 343 | jffs2_do_clear_inode(c, f); | 351 | jffs2_do_clear_inode(c, f); |
| 344 | iget_failed(inode); | 352 | iget_failed(inode); |
| 345 | return ERR_PTR(ret); | 353 | return ERR_PTR(ret); |
| @@ -380,9 +388,9 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data) | |||
| 380 | Flush the writebuffer, if neccecary, else we loose it */ | 388 | Flush the writebuffer, if neccecary, else we loose it */ |
| 381 | if (!(sb->s_flags & MS_RDONLY)) { | 389 | if (!(sb->s_flags & MS_RDONLY)) { |
| 382 | jffs2_stop_garbage_collect_thread(c); | 390 | jffs2_stop_garbage_collect_thread(c); |
| 383 | down(&c->alloc_sem); | 391 | mutex_lock(&c->alloc_sem); |
| 384 | jffs2_flush_wbuf_pad(c); | 392 | jffs2_flush_wbuf_pad(c); |
| 385 | up(&c->alloc_sem); | 393 | mutex_unlock(&c->alloc_sem); |
| 386 | } | 394 | } |
| 387 | 395 | ||
| 388 | if (!(*flags & MS_RDONLY)) | 396 | if (!(*flags & MS_RDONLY)) |
| @@ -429,7 +437,7 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i | |||
| 429 | 437 | ||
| 430 | f = JFFS2_INODE_INFO(inode); | 438 | f = JFFS2_INODE_INFO(inode); |
| 431 | jffs2_init_inode_info(f); | 439 | jffs2_init_inode_info(f); |
| 432 | down(&f->sem); | 440 | mutex_lock(&f->sem); |
| 433 | 441 | ||
| 434 | memset(ri, 0, sizeof(*ri)); | 442 | memset(ri, 0, sizeof(*ri)); |
| 435 | /* Set OS-specific defaults for new inodes */ | 443 | /* Set OS-specific defaults for new inodes */ |
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 32ff0373aa04..bad005664e30 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c | |||
| @@ -126,7 +126,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
| 126 | int ret = 0, inum, nlink; | 126 | int ret = 0, inum, nlink; |
| 127 | int xattr = 0; | 127 | int xattr = 0; |
| 128 | 128 | ||
| 129 | if (down_interruptible(&c->alloc_sem)) | 129 | if (mutex_lock_interruptible(&c->alloc_sem)) |
| 130 | return -EINTR; | 130 | return -EINTR; |
| 131 | 131 | ||
| 132 | for (;;) { | 132 | for (;;) { |
| @@ -143,7 +143,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
| 143 | c->unchecked_size); | 143 | c->unchecked_size); |
| 144 | jffs2_dbg_dump_block_lists_nolock(c); | 144 | jffs2_dbg_dump_block_lists_nolock(c); |
| 145 | spin_unlock(&c->erase_completion_lock); | 145 | spin_unlock(&c->erase_completion_lock); |
| 146 | up(&c->alloc_sem); | 146 | mutex_unlock(&c->alloc_sem); |
| 147 | return -ENOSPC; | 147 | return -ENOSPC; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| @@ -190,7 +190,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
| 190 | made no progress in this case, but that should be OK */ | 190 | made no progress in this case, but that should be OK */ |
| 191 | c->checked_ino--; | 191 | c->checked_ino--; |
| 192 | 192 | ||
| 193 | up(&c->alloc_sem); | 193 | mutex_unlock(&c->alloc_sem); |
| 194 | sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); | 194 | sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); |
| 195 | return 0; | 195 | return 0; |
| 196 | 196 | ||
| @@ -210,7 +210,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
| 210 | printk(KERN_WARNING "Returned error for crccheck of ino #%u. Expect badness...\n", ic->ino); | 210 | printk(KERN_WARNING "Returned error for crccheck of ino #%u. Expect badness...\n", ic->ino); |
| 211 | 211 | ||
| 212 | jffs2_set_inocache_state(c, ic, INO_STATE_CHECKEDABSENT); | 212 | jffs2_set_inocache_state(c, ic, INO_STATE_CHECKEDABSENT); |
| 213 | up(&c->alloc_sem); | 213 | mutex_unlock(&c->alloc_sem); |
| 214 | return ret; | 214 | return ret; |
| 215 | } | 215 | } |
| 216 | 216 | ||
| @@ -221,9 +221,15 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
| 221 | jeb = jffs2_find_gc_block(c); | 221 | jeb = jffs2_find_gc_block(c); |
| 222 | 222 | ||
| 223 | if (!jeb) { | 223 | if (!jeb) { |
| 224 | D1 (printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n")); | 224 | /* Couldn't find a free block. But maybe we can just erase one and make 'progress'? */ |
| 225 | if (!list_empty(&c->erase_pending_list)) { | ||
| 226 | spin_unlock(&c->erase_completion_lock); | ||
| 227 | mutex_unlock(&c->alloc_sem); | ||
| 228 | return -EAGAIN; | ||
| 229 | } | ||
| 230 | D1(printk(KERN_NOTICE "jffs2: Couldn't find erase block to garbage collect!\n")); | ||
| 225 | spin_unlock(&c->erase_completion_lock); | 231 | spin_unlock(&c->erase_completion_lock); |
| 226 | up(&c->alloc_sem); | 232 | mutex_unlock(&c->alloc_sem); |
| 227 | return -EIO; | 233 | return -EIO; |
| 228 | } | 234 | } |
| 229 | 235 | ||
| @@ -232,7 +238,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
| 232 | printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size %08x, wasted_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->free_size)); | 238 | printk(KERN_DEBUG "Nextblock at %08x, used_size %08x, dirty_size %08x, wasted_size %08x, free_size %08x\n", c->nextblock->offset, c->nextblock->used_size, c->nextblock->dirty_size, c->nextblock->wasted_size, c->nextblock->free_size)); |
| 233 | 239 | ||
| 234 | if (!jeb->used_size) { | 240 | if (!jeb->used_size) { |
| 235 | up(&c->alloc_sem); | 241 | mutex_unlock(&c->alloc_sem); |
| 236 | goto eraseit; | 242 | goto eraseit; |
| 237 | } | 243 | } |
| 238 | 244 | ||
| @@ -248,7 +254,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
| 248 | jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size); | 254 | jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size); |
| 249 | jeb->gc_node = raw; | 255 | jeb->gc_node = raw; |
| 250 | spin_unlock(&c->erase_completion_lock); | 256 | spin_unlock(&c->erase_completion_lock); |
| 251 | up(&c->alloc_sem); | 257 | mutex_unlock(&c->alloc_sem); |
| 252 | BUG(); | 258 | BUG(); |
| 253 | } | 259 | } |
| 254 | } | 260 | } |
| @@ -266,7 +272,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
| 266 | /* Just mark it obsolete */ | 272 | /* Just mark it obsolete */ |
| 267 | jffs2_mark_node_obsolete(c, raw); | 273 | jffs2_mark_node_obsolete(c, raw); |
| 268 | } | 274 | } |
| 269 | up(&c->alloc_sem); | 275 | mutex_unlock(&c->alloc_sem); |
| 270 | goto eraseit_lock; | 276 | goto eraseit_lock; |
| 271 | } | 277 | } |
| 272 | 278 | ||
| @@ -334,7 +340,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
| 334 | */ | 340 | */ |
| 335 | printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n", | 341 | printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n", |
| 336 | ic->ino, ic->state); | 342 | ic->ino, ic->state); |
| 337 | up(&c->alloc_sem); | 343 | mutex_unlock(&c->alloc_sem); |
| 338 | spin_unlock(&c->inocache_lock); | 344 | spin_unlock(&c->inocache_lock); |
| 339 | BUG(); | 345 | BUG(); |
| 340 | 346 | ||
| @@ -345,7 +351,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
| 345 | the alloc_sem() (for marking nodes invalid) so we must | 351 | the alloc_sem() (for marking nodes invalid) so we must |
| 346 | drop the alloc_sem before sleeping. */ | 352 | drop the alloc_sem before sleeping. */ |
| 347 | 353 | ||
| 348 | up(&c->alloc_sem); | 354 | mutex_unlock(&c->alloc_sem); |
| 349 | D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() waiting for ino #%u in state %d\n", | 355 | D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() waiting for ino #%u in state %d\n", |
| 350 | ic->ino, ic->state)); | 356 | ic->ino, ic->state)); |
| 351 | sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); | 357 | sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); |
| @@ -416,7 +422,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
| 416 | ret = -ENOSPC; | 422 | ret = -ENOSPC; |
| 417 | } | 423 | } |
| 418 | release_sem: | 424 | release_sem: |
| 419 | up(&c->alloc_sem); | 425 | mutex_unlock(&c->alloc_sem); |
| 420 | 426 | ||
| 421 | eraseit_lock: | 427 | eraseit_lock: |
| 422 | /* If we've finished this block, start it erasing */ | 428 | /* If we've finished this block, start it erasing */ |
| @@ -445,7 +451,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era | |||
| 445 | uint32_t start = 0, end = 0, nrfrags = 0; | 451 | uint32_t start = 0, end = 0, nrfrags = 0; |
| 446 | int ret = 0; | 452 | int ret = 0; |
| 447 | 453 | ||
| 448 | down(&f->sem); | 454 | mutex_lock(&f->sem); |
| 449 | 455 | ||
| 450 | /* Now we have the lock for this inode. Check that it's still the one at the head | 456 | /* Now we have the lock for this inode. Check that it's still the one at the head |
| 451 | of the list. */ | 457 | of the list. */ |
| @@ -525,7 +531,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era | |||
| 525 | } | 531 | } |
| 526 | } | 532 | } |
| 527 | upnout: | 533 | upnout: |
| 528 | up(&f->sem); | 534 | mutex_unlock(&f->sem); |
| 529 | 535 | ||
| 530 | return ret; | 536 | return ret; |
| 531 | } | 537 | } |
| @@ -846,7 +852,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct | |||
| 846 | /* Prevent the erase code from nicking the obsolete node refs while | 852 | /* Prevent the erase code from nicking the obsolete node refs while |
| 847 | we're looking at them. I really don't like this extra lock but | 853 | we're looking at them. I really don't like this extra lock but |
| 848 | can't see any alternative. Suggestions on a postcard to... */ | 854 | can't see any alternative. Suggestions on a postcard to... */ |
| 849 | down(&c->erase_free_sem); | 855 | mutex_lock(&c->erase_free_sem); |
| 850 | 856 | ||
| 851 | for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) { | 857 | for (raw = f->inocache->nodes; raw != (void *)f->inocache; raw = raw->next_in_ino) { |
| 852 | 858 | ||
| @@ -899,7 +905,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct | |||
| 899 | /* OK. The name really does match. There really is still an older node on | 905 | /* OK. The name really does match. There really is still an older node on |
| 900 | the flash which our deletion dirent obsoletes. So we have to write out | 906 | the flash which our deletion dirent obsoletes. So we have to write out |
| 901 | a new deletion dirent to replace it */ | 907 | a new deletion dirent to replace it */ |
| 902 | up(&c->erase_free_sem); | 908 | mutex_unlock(&c->erase_free_sem); |
| 903 | 909 | ||
| 904 | D1(printk(KERN_DEBUG "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n", | 910 | D1(printk(KERN_DEBUG "Deletion dirent at %08x still obsoletes real dirent \"%s\" at %08x for ino #%u\n", |
| 905 | ref_offset(fd->raw), fd->name, ref_offset(raw), je32_to_cpu(rd->ino))); | 911 | ref_offset(fd->raw), fd->name, ref_offset(raw), je32_to_cpu(rd->ino))); |
| @@ -908,7 +914,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct | |||
| 908 | return jffs2_garbage_collect_dirent(c, jeb, f, fd); | 914 | return jffs2_garbage_collect_dirent(c, jeb, f, fd); |
| 909 | } | 915 | } |
| 910 | 916 | ||
| 911 | up(&c->erase_free_sem); | 917 | mutex_unlock(&c->erase_free_sem); |
| 912 | kfree(rd); | 918 | kfree(rd); |
| 913 | } | 919 | } |
| 914 | 920 | ||
| @@ -1081,7 +1087,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras | |||
| 1081 | return 0; | 1087 | return 0; |
| 1082 | } | 1088 | } |
| 1083 | 1089 | ||
| 1084 | static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 1090 | static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *orig_jeb, |
| 1085 | struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, | 1091 | struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, |
| 1086 | uint32_t start, uint32_t end) | 1092 | uint32_t start, uint32_t end) |
| 1087 | { | 1093 | { |
diff --git a/fs/jffs2/ioctl.c b/fs/jffs2/ioctl.c index f4d525b0ea53..e2177210f621 100644 --- a/fs/jffs2/ioctl.c +++ b/fs/jffs2/ioctl.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
| 13 | #include "nodelist.h" | ||
| 13 | 14 | ||
| 14 | int jffs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, | 15 | int jffs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, |
| 15 | unsigned long arg) | 16 | unsigned long arg) |
diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h index a841f4973a74..31559f45fdde 100644 --- a/fs/jffs2/jffs2_fs_i.h +++ b/fs/jffs2/jffs2_fs_i.h | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | #include <linux/version.h> | 15 | #include <linux/version.h> |
| 16 | #include <linux/rbtree.h> | 16 | #include <linux/rbtree.h> |
| 17 | #include <linux/posix_acl.h> | 17 | #include <linux/posix_acl.h> |
| 18 | #include <linux/semaphore.h> | 18 | #include <linux/mutex.h> |
| 19 | 19 | ||
| 20 | struct jffs2_inode_info { | 20 | struct jffs2_inode_info { |
| 21 | /* We need an internal mutex similar to inode->i_mutex. | 21 | /* We need an internal mutex similar to inode->i_mutex. |
| @@ -24,7 +24,7 @@ struct jffs2_inode_info { | |||
| 24 | before letting GC proceed. Or we'd have to put ugliness | 24 | before letting GC proceed. Or we'd have to put ugliness |
| 25 | into the GC code so it didn't attempt to obtain the i_mutex | 25 | into the GC code so it didn't attempt to obtain the i_mutex |
| 26 | for the inode(s) which are already locked */ | 26 | for the inode(s) which are already locked */ |
| 27 | struct semaphore sem; | 27 | struct mutex sem; |
| 28 | 28 | ||
| 29 | /* The highest (datanode) version number used for this ino */ | 29 | /* The highest (datanode) version number used for this ino */ |
| 30 | uint32_t highest_version; | 30 | uint32_t highest_version; |
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 18fca2b9e531..85ef6dbb1be7 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | #include <linux/spinlock.h> | 16 | #include <linux/spinlock.h> |
| 17 | #include <linux/workqueue.h> | 17 | #include <linux/workqueue.h> |
| 18 | #include <linux/completion.h> | 18 | #include <linux/completion.h> |
| 19 | #include <linux/semaphore.h> | 19 | #include <linux/mutex.h> |
| 20 | #include <linux/timer.h> | 20 | #include <linux/timer.h> |
| 21 | #include <linux/wait.h> | 21 | #include <linux/wait.h> |
| 22 | #include <linux/list.h> | 22 | #include <linux/list.h> |
| @@ -44,7 +44,7 @@ struct jffs2_sb_info { | |||
| 44 | struct completion gc_thread_start; /* GC thread start completion */ | 44 | struct completion gc_thread_start; /* GC thread start completion */ |
| 45 | struct completion gc_thread_exit; /* GC thread exit completion port */ | 45 | struct completion gc_thread_exit; /* GC thread exit completion port */ |
| 46 | 46 | ||
| 47 | struct semaphore alloc_sem; /* Used to protect all the following | 47 | struct mutex alloc_sem; /* Used to protect all the following |
| 48 | fields, and also to protect against | 48 | fields, and also to protect against |
| 49 | out-of-order writing of nodes. And GC. */ | 49 | out-of-order writing of nodes. And GC. */ |
| 50 | uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER | 50 | uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER |
| @@ -87,6 +87,7 @@ struct jffs2_sb_info { | |||
| 87 | struct list_head erasable_list; /* Blocks which are completely dirty, and need erasing */ | 87 | struct list_head erasable_list; /* Blocks which are completely dirty, and need erasing */ |
| 88 | struct list_head erasable_pending_wbuf_list; /* Blocks which need erasing but only after the current wbuf is flushed */ | 88 | struct list_head erasable_pending_wbuf_list; /* Blocks which need erasing but only after the current wbuf is flushed */ |
| 89 | struct list_head erasing_list; /* Blocks which are currently erasing */ | 89 | struct list_head erasing_list; /* Blocks which are currently erasing */ |
| 90 | struct list_head erase_checking_list; /* Blocks which are being checked and marked */ | ||
| 90 | struct list_head erase_pending_list; /* Blocks which need erasing now */ | 91 | struct list_head erase_pending_list; /* Blocks which need erasing now */ |
| 91 | struct list_head erase_complete_list; /* Blocks which are erased and need the clean marker written to them */ | 92 | struct list_head erase_complete_list; /* Blocks which are erased and need the clean marker written to them */ |
| 92 | struct list_head free_list; /* Blocks which are free and ready to be used */ | 93 | struct list_head free_list; /* Blocks which are free and ready to be used */ |
| @@ -104,7 +105,7 @@ struct jffs2_sb_info { | |||
| 104 | /* Sem to allow jffs2_garbage_collect_deletion_dirent to | 105 | /* Sem to allow jffs2_garbage_collect_deletion_dirent to |
| 105 | drop the erase_completion_lock while it's holding a pointer | 106 | drop the erase_completion_lock while it's holding a pointer |
| 106 | to an obsoleted node. I don't like this. Alternatives welcomed. */ | 107 | to an obsoleted node. I don't like this. Alternatives welcomed. */ |
| 107 | struct semaphore erase_free_sem; | 108 | struct mutex erase_free_sem; |
| 108 | 109 | ||
| 109 | uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */ | 110 | uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */ |
| 110 | 111 | ||
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index ec1aae9e695e..8219df6eb6d8 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h | |||
| @@ -87,7 +87,7 @@ struct jffs2_raw_node_ref | |||
| 87 | xattr_ref or xattr_datum instead. The common part of those structures | 87 | xattr_ref or xattr_datum instead. The common part of those structures |
| 88 | has NULL in the first word. See jffs2_raw_ref_to_ic() below */ | 88 | has NULL in the first word. See jffs2_raw_ref_to_ic() below */ |
| 89 | uint32_t flash_offset; | 89 | uint32_t flash_offset; |
| 90 | #define TEST_TOTLEN | 90 | #undef TEST_TOTLEN |
| 91 | #ifdef TEST_TOTLEN | 91 | #ifdef TEST_TOTLEN |
| 92 | uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */ | 92 | uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */ |
| 93 | #endif | 93 | #endif |
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index a0313fa8748e..9df8f3ef20df 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c | |||
| @@ -48,7 +48,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
| 48 | minsize = PAD(minsize); | 48 | minsize = PAD(minsize); |
| 49 | 49 | ||
| 50 | D1(printk(KERN_DEBUG "jffs2_reserve_space(): Requested 0x%x bytes\n", minsize)); | 50 | D1(printk(KERN_DEBUG "jffs2_reserve_space(): Requested 0x%x bytes\n", minsize)); |
| 51 | down(&c->alloc_sem); | 51 | mutex_lock(&c->alloc_sem); |
| 52 | 52 | ||
| 53 | D1(printk(KERN_DEBUG "jffs2_reserve_space(): alloc sem got\n")); | 53 | D1(printk(KERN_DEBUG "jffs2_reserve_space(): alloc sem got\n")); |
| 54 | 54 | ||
| @@ -57,7 +57,6 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
| 57 | /* this needs a little more thought (true <tglx> :)) */ | 57 | /* this needs a little more thought (true <tglx> :)) */ |
| 58 | while(ret == -EAGAIN) { | 58 | while(ret == -EAGAIN) { |
| 59 | while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) { | 59 | while(c->nr_free_blocks + c->nr_erasing_blocks < blocksneeded) { |
| 60 | int ret; | ||
| 61 | uint32_t dirty, avail; | 60 | uint32_t dirty, avail; |
| 62 | 61 | ||
| 63 | /* calculate real dirty size | 62 | /* calculate real dirty size |
| @@ -82,7 +81,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
| 82 | dirty, c->unchecked_size, c->sector_size)); | 81 | dirty, c->unchecked_size, c->sector_size)); |
| 83 | 82 | ||
| 84 | spin_unlock(&c->erase_completion_lock); | 83 | spin_unlock(&c->erase_completion_lock); |
| 85 | up(&c->alloc_sem); | 84 | mutex_unlock(&c->alloc_sem); |
| 86 | return -ENOSPC; | 85 | return -ENOSPC; |
| 87 | } | 86 | } |
| 88 | 87 | ||
| @@ -105,11 +104,11 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
| 105 | D1(printk(KERN_DEBUG "max. available size 0x%08x < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n", | 104 | D1(printk(KERN_DEBUG "max. available size 0x%08x < blocksneeded * sector_size 0x%08x, returning -ENOSPC\n", |
| 106 | avail, blocksneeded * c->sector_size)); | 105 | avail, blocksneeded * c->sector_size)); |
| 107 | spin_unlock(&c->erase_completion_lock); | 106 | spin_unlock(&c->erase_completion_lock); |
| 108 | up(&c->alloc_sem); | 107 | mutex_unlock(&c->alloc_sem); |
| 109 | return -ENOSPC; | 108 | return -ENOSPC; |
| 110 | } | 109 | } |
| 111 | 110 | ||
| 112 | up(&c->alloc_sem); | 111 | mutex_unlock(&c->alloc_sem); |
| 113 | 112 | ||
| 114 | D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, wasted_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n", | 113 | D1(printk(KERN_DEBUG "Triggering GC pass. nr_free_blocks %d, nr_erasing_blocks %d, free_size 0x%08x, dirty_size 0x%08x, wasted_size 0x%08x, used_size 0x%08x, erasing_size 0x%08x, bad_size 0x%08x (total 0x%08x of 0x%08x)\n", |
| 115 | c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->wasted_size, c->used_size, c->erasing_size, c->bad_size, | 114 | c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->wasted_size, c->used_size, c->erasing_size, c->bad_size, |
| @@ -117,7 +116,10 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
| 117 | spin_unlock(&c->erase_completion_lock); | 116 | spin_unlock(&c->erase_completion_lock); |
| 118 | 117 | ||
| 119 | ret = jffs2_garbage_collect_pass(c); | 118 | ret = jffs2_garbage_collect_pass(c); |
| 120 | if (ret) | 119 | |
| 120 | if (ret == -EAGAIN) | ||
| 121 | jffs2_erase_pending_blocks(c, 1); | ||
| 122 | else if (ret) | ||
| 121 | return ret; | 123 | return ret; |
| 122 | 124 | ||
| 123 | cond_resched(); | 125 | cond_resched(); |
| @@ -125,7 +127,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
| 125 | if (signal_pending(current)) | 127 | if (signal_pending(current)) |
| 126 | return -EINTR; | 128 | return -EINTR; |
| 127 | 129 | ||
| 128 | down(&c->alloc_sem); | 130 | mutex_lock(&c->alloc_sem); |
| 129 | spin_lock(&c->erase_completion_lock); | 131 | spin_lock(&c->erase_completion_lock); |
| 130 | } | 132 | } |
| 131 | 133 | ||
| @@ -138,7 +140,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | |||
| 138 | if (!ret) | 140 | if (!ret) |
| 139 | ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1); | 141 | ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1); |
| 140 | if (ret) | 142 | if (ret) |
| 141 | up(&c->alloc_sem); | 143 | mutex_unlock(&c->alloc_sem); |
| 142 | return ret; | 144 | return ret; |
| 143 | } | 145 | } |
| 144 | 146 | ||
| @@ -463,7 +465,7 @@ void jffs2_complete_reservation(struct jffs2_sb_info *c) | |||
| 463 | { | 465 | { |
| 464 | D1(printk(KERN_DEBUG "jffs2_complete_reservation()\n")); | 466 | D1(printk(KERN_DEBUG "jffs2_complete_reservation()\n")); |
| 465 | jffs2_garbage_collect_trigger(c); | 467 | jffs2_garbage_collect_trigger(c); |
| 466 | up(&c->alloc_sem); | 468 | mutex_unlock(&c->alloc_sem); |
| 467 | } | 469 | } |
| 468 | 470 | ||
| 469 | static inline int on_list(struct list_head *obj, struct list_head *head) | 471 | static inline int on_list(struct list_head *obj, struct list_head *head) |
| @@ -512,7 +514,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
| 512 | any jffs2_raw_node_refs. So we don't need to stop erases from | 514 | any jffs2_raw_node_refs. So we don't need to stop erases from |
| 513 | happening, or protect against people holding an obsolete | 515 | happening, or protect against people holding an obsolete |
| 514 | jffs2_raw_node_ref without the erase_completion_lock. */ | 516 | jffs2_raw_node_ref without the erase_completion_lock. */ |
| 515 | down(&c->erase_free_sem); | 517 | mutex_lock(&c->erase_free_sem); |
| 516 | } | 518 | } |
| 517 | 519 | ||
| 518 | spin_lock(&c->erase_completion_lock); | 520 | spin_lock(&c->erase_completion_lock); |
| @@ -715,7 +717,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
| 715 | } | 717 | } |
| 716 | 718 | ||
| 717 | out_erase_sem: | 719 | out_erase_sem: |
| 718 | up(&c->erase_free_sem); | 720 | mutex_unlock(&c->erase_free_sem); |
| 719 | } | 721 | } |
| 720 | 722 | ||
| 721 | int jffs2_thread_should_wake(struct jffs2_sb_info *c) | 723 | int jffs2_thread_should_wake(struct jffs2_sb_info *c) |
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index e512a93d6249..4cb4d76de07f 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c | |||
| @@ -825,8 +825,9 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
| 825 | else // normal case... | 825 | else // normal case... |
| 826 | tn->fn->size = je32_to_cpu(rd->dsize); | 826 | tn->fn->size = je32_to_cpu(rd->dsize); |
| 827 | 827 | ||
| 828 | dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", | 828 | dbg_readinode2("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", |
| 829 | ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); | 829 | ref_offset(ref), je32_to_cpu(rd->version), |
| 830 | je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); | ||
| 830 | 831 | ||
| 831 | ret = jffs2_add_tn_to_tree(c, rii, tn); | 832 | ret = jffs2_add_tn_to_tree(c, rii, tn); |
| 832 | 833 | ||
| @@ -836,13 +837,13 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
| 836 | jffs2_free_tmp_dnode_info(tn); | 837 | jffs2_free_tmp_dnode_info(tn); |
| 837 | return ret; | 838 | return ret; |
| 838 | } | 839 | } |
| 839 | #ifdef JFFS2_DBG_READINODE_MESSAGES | 840 | #ifdef JFFS2_DBG_READINODE2_MESSAGES |
| 840 | dbg_readinode("After adding ver %d:\n", je32_to_cpu(rd->version)); | 841 | dbg_readinode2("After adding ver %d:\n", je32_to_cpu(rd->version)); |
| 841 | tn = tn_first(&rii->tn_root); | 842 | tn = tn_first(&rii->tn_root); |
| 842 | while (tn) { | 843 | while (tn) { |
| 843 | dbg_readinode("%p: v %d r 0x%x-0x%x ov %d\n", | 844 | dbg_readinode2("%p: v %d r 0x%x-0x%x ov %d\n", |
| 844 | tn, tn->version, tn->fn->ofs, | 845 | tn, tn->version, tn->fn->ofs, |
| 845 | tn->fn->ofs+tn->fn->size, tn->overlapped); | 846 | tn->fn->ofs+tn->fn->size, tn->overlapped); |
| 846 | tn = tn_next(tn); | 847 | tn = tn_next(tn); |
| 847 | } | 848 | } |
| 848 | #endif | 849 | #endif |
| @@ -1193,7 +1194,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
| 1193 | JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n", | 1194 | JFFS2_ERROR("failed to read from flash: error %d, %zd of %zd bytes read\n", |
| 1194 | ret, retlen, sizeof(*latest_node)); | 1195 | ret, retlen, sizeof(*latest_node)); |
| 1195 | /* FIXME: If this fails, there seems to be a memory leak. Find it. */ | 1196 | /* FIXME: If this fails, there seems to be a memory leak. Find it. */ |
| 1196 | up(&f->sem); | 1197 | mutex_unlock(&f->sem); |
| 1197 | jffs2_do_clear_inode(c, f); | 1198 | jffs2_do_clear_inode(c, f); |
| 1198 | return ret?ret:-EIO; | 1199 | return ret?ret:-EIO; |
| 1199 | } | 1200 | } |
| @@ -1202,7 +1203,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
| 1202 | if (crc != je32_to_cpu(latest_node->node_crc)) { | 1203 | if (crc != je32_to_cpu(latest_node->node_crc)) { |
| 1203 | JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n", | 1204 | JFFS2_ERROR("CRC failed for read_inode of inode %u at physical location 0x%x\n", |
| 1204 | f->inocache->ino, ref_offset(rii.latest_ref)); | 1205 | f->inocache->ino, ref_offset(rii.latest_ref)); |
| 1205 | up(&f->sem); | 1206 | mutex_unlock(&f->sem); |
| 1206 | jffs2_do_clear_inode(c, f); | 1207 | jffs2_do_clear_inode(c, f); |
| 1207 | return -EIO; | 1208 | return -EIO; |
| 1208 | } | 1209 | } |
| @@ -1242,7 +1243,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
| 1242 | f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); | 1243 | f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); |
| 1243 | if (!f->target) { | 1244 | if (!f->target) { |
| 1244 | JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize)); | 1245 | JFFS2_ERROR("can't allocate %d bytes of memory for the symlink target path cache\n", je32_to_cpu(latest_node->csize)); |
| 1245 | up(&f->sem); | 1246 | mutex_unlock(&f->sem); |
| 1246 | jffs2_do_clear_inode(c, f); | 1247 | jffs2_do_clear_inode(c, f); |
| 1247 | return -ENOMEM; | 1248 | return -ENOMEM; |
| 1248 | } | 1249 | } |
| @@ -1255,7 +1256,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
| 1255 | ret = -EIO; | 1256 | ret = -EIO; |
| 1256 | kfree(f->target); | 1257 | kfree(f->target); |
| 1257 | f->target = NULL; | 1258 | f->target = NULL; |
| 1258 | up(&f->sem); | 1259 | mutex_unlock(&f->sem); |
| 1259 | jffs2_do_clear_inode(c, f); | 1260 | jffs2_do_clear_inode(c, f); |
| 1260 | return -ret; | 1261 | return -ret; |
| 1261 | } | 1262 | } |
| @@ -1273,14 +1274,14 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
| 1273 | if (f->metadata) { | 1274 | if (f->metadata) { |
| 1274 | JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n", | 1275 | JFFS2_ERROR("Argh. Special inode #%u with mode 0%o had metadata node\n", |
| 1275 | f->inocache->ino, jemode_to_cpu(latest_node->mode)); | 1276 | f->inocache->ino, jemode_to_cpu(latest_node->mode)); |
| 1276 | up(&f->sem); | 1277 | mutex_unlock(&f->sem); |
| 1277 | jffs2_do_clear_inode(c, f); | 1278 | jffs2_do_clear_inode(c, f); |
| 1278 | return -EIO; | 1279 | return -EIO; |
| 1279 | } | 1280 | } |
| 1280 | if (!frag_first(&f->fragtree)) { | 1281 | if (!frag_first(&f->fragtree)) { |
| 1281 | JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n", | 1282 | JFFS2_ERROR("Argh. Special inode #%u with mode 0%o has no fragments\n", |
| 1282 | f->inocache->ino, jemode_to_cpu(latest_node->mode)); | 1283 | f->inocache->ino, jemode_to_cpu(latest_node->mode)); |
| 1283 | up(&f->sem); | 1284 | mutex_unlock(&f->sem); |
| 1284 | jffs2_do_clear_inode(c, f); | 1285 | jffs2_do_clear_inode(c, f); |
| 1285 | return -EIO; | 1286 | return -EIO; |
| 1286 | } | 1287 | } |
| @@ -1289,7 +1290,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
| 1289 | JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n", | 1290 | JFFS2_ERROR("Argh. Special inode #%u with mode 0x%x had more than one node\n", |
| 1290 | f->inocache->ino, jemode_to_cpu(latest_node->mode)); | 1291 | f->inocache->ino, jemode_to_cpu(latest_node->mode)); |
| 1291 | /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ | 1292 | /* FIXME: Deal with it - check crc32, check for duplicate node, check times and discard the older one */ |
| 1292 | up(&f->sem); | 1293 | mutex_unlock(&f->sem); |
| 1293 | jffs2_do_clear_inode(c, f); | 1294 | jffs2_do_clear_inode(c, f); |
| 1294 | return -EIO; | 1295 | return -EIO; |
| 1295 | } | 1296 | } |
| @@ -1379,12 +1380,13 @@ int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *i | |||
| 1379 | if (!f) | 1380 | if (!f) |
| 1380 | return -ENOMEM; | 1381 | return -ENOMEM; |
| 1381 | 1382 | ||
| 1382 | init_MUTEX_LOCKED(&f->sem); | 1383 | mutex_init(&f->sem); |
| 1384 | mutex_lock(&f->sem); | ||
| 1383 | f->inocache = ic; | 1385 | f->inocache = ic; |
| 1384 | 1386 | ||
| 1385 | ret = jffs2_do_read_inode_internal(c, f, &n); | 1387 | ret = jffs2_do_read_inode_internal(c, f, &n); |
| 1386 | if (!ret) { | 1388 | if (!ret) { |
| 1387 | up(&f->sem); | 1389 | mutex_unlock(&f->sem); |
| 1388 | jffs2_do_clear_inode(c, f); | 1390 | jffs2_do_clear_inode(c, f); |
| 1389 | } | 1391 | } |
| 1390 | kfree (f); | 1392 | kfree (f); |
| @@ -1398,7 +1400,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) | |||
| 1398 | 1400 | ||
| 1399 | jffs2_clear_acl(f); | 1401 | jffs2_clear_acl(f); |
| 1400 | jffs2_xattr_delete_inode(c, f->inocache); | 1402 | jffs2_xattr_delete_inode(c, f->inocache); |
| 1401 | down(&f->sem); | 1403 | mutex_lock(&f->sem); |
| 1402 | deleted = f->inocache && !f->inocache->nlink; | 1404 | deleted = f->inocache && !f->inocache->nlink; |
| 1403 | 1405 | ||
| 1404 | if (f->inocache && f->inocache->state != INO_STATE_CHECKING) | 1406 | if (f->inocache && f->inocache->state != INO_STATE_CHECKING) |
| @@ -1430,5 +1432,5 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) | |||
| 1430 | jffs2_del_ino_cache(c, f->inocache); | 1432 | jffs2_del_ino_cache(c, f->inocache); |
| 1431 | } | 1433 | } |
| 1432 | 1434 | ||
| 1433 | up(&f->sem); | 1435 | mutex_unlock(&f->sem); |
| 1434 | } | 1436 | } |
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 4677355996cc..f3353df178e7 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c | |||
| @@ -47,7 +47,7 @@ static void jffs2_i_init_once(struct kmem_cache *cachep, void *foo) | |||
| 47 | { | 47 | { |
| 48 | struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo; | 48 | struct jffs2_inode_info *ei = (struct jffs2_inode_info *) foo; |
| 49 | 49 | ||
| 50 | init_MUTEX(&ei->sem); | 50 | mutex_init(&ei->sem); |
| 51 | inode_init_once(&ei->vfs_inode); | 51 | inode_init_once(&ei->vfs_inode); |
| 52 | } | 52 | } |
| 53 | 53 | ||
| @@ -55,9 +55,9 @@ static int jffs2_sync_fs(struct super_block *sb, int wait) | |||
| 55 | { | 55 | { |
| 56 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | 56 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); |
| 57 | 57 | ||
| 58 | down(&c->alloc_sem); | 58 | mutex_lock(&c->alloc_sem); |
| 59 | jffs2_flush_wbuf_pad(c); | 59 | jffs2_flush_wbuf_pad(c); |
| 60 | up(&c->alloc_sem); | 60 | mutex_unlock(&c->alloc_sem); |
| 61 | return 0; | 61 | return 0; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| @@ -95,8 +95,8 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent) | |||
| 95 | 95 | ||
| 96 | /* Initialize JFFS2 superblock locks, the further initialization will | 96 | /* Initialize JFFS2 superblock locks, the further initialization will |
| 97 | * be done later */ | 97 | * be done later */ |
| 98 | init_MUTEX(&c->alloc_sem); | 98 | mutex_init(&c->alloc_sem); |
| 99 | init_MUTEX(&c->erase_free_sem); | 99 | mutex_init(&c->erase_free_sem); |
| 100 | init_waitqueue_head(&c->erase_wait); | 100 | init_waitqueue_head(&c->erase_wait); |
| 101 | init_waitqueue_head(&c->inocache_wq); | 101 | init_waitqueue_head(&c->inocache_wq); |
| 102 | spin_lock_init(&c->erase_completion_lock); | 102 | spin_lock_init(&c->erase_completion_lock); |
| @@ -125,9 +125,9 @@ static void jffs2_put_super (struct super_block *sb) | |||
| 125 | 125 | ||
| 126 | D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n")); | 126 | D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n")); |
| 127 | 127 | ||
| 128 | down(&c->alloc_sem); | 128 | mutex_lock(&c->alloc_sem); |
| 129 | jffs2_flush_wbuf_pad(c); | 129 | jffs2_flush_wbuf_pad(c); |
| 130 | up(&c->alloc_sem); | 130 | mutex_unlock(&c->alloc_sem); |
| 131 | 131 | ||
| 132 | jffs2_sum_exit(c); | 132 | jffs2_sum_exit(c); |
| 133 | 133 | ||
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index d1d4f27464ba..8de52b607678 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c | |||
| @@ -578,8 +578,8 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
| 578 | if (!jffs2_is_writebuffered(c)) | 578 | if (!jffs2_is_writebuffered(c)) |
| 579 | return 0; | 579 | return 0; |
| 580 | 580 | ||
| 581 | if (!down_trylock(&c->alloc_sem)) { | 581 | if (mutex_trylock(&c->alloc_sem)) { |
| 582 | up(&c->alloc_sem); | 582 | mutex_unlock(&c->alloc_sem); |
| 583 | printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n"); | 583 | printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n"); |
| 584 | BUG(); | 584 | BUG(); |
| 585 | } | 585 | } |
| @@ -702,10 +702,10 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino) | |||
| 702 | if (!c->wbuf) | 702 | if (!c->wbuf) |
| 703 | return 0; | 703 | return 0; |
| 704 | 704 | ||
| 705 | down(&c->alloc_sem); | 705 | mutex_lock(&c->alloc_sem); |
| 706 | if (!jffs2_wbuf_pending_for_ino(c, ino)) { | 706 | if (!jffs2_wbuf_pending_for_ino(c, ino)) { |
| 707 | D1(printk(KERN_DEBUG "Ino #%d not pending in wbuf. Returning\n", ino)); | 707 | D1(printk(KERN_DEBUG "Ino #%d not pending in wbuf. Returning\n", ino)); |
| 708 | up(&c->alloc_sem); | 708 | mutex_unlock(&c->alloc_sem); |
| 709 | return 0; | 709 | return 0; |
| 710 | } | 710 | } |
| 711 | 711 | ||
| @@ -725,14 +725,14 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino) | |||
| 725 | } else while (old_wbuf_len && | 725 | } else while (old_wbuf_len && |
| 726 | old_wbuf_ofs == c->wbuf_ofs) { | 726 | old_wbuf_ofs == c->wbuf_ofs) { |
| 727 | 727 | ||
| 728 | up(&c->alloc_sem); | 728 | mutex_unlock(&c->alloc_sem); |
| 729 | 729 | ||
| 730 | D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() calls gc pass\n")); | 730 | D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() calls gc pass\n")); |
| 731 | 731 | ||
| 732 | ret = jffs2_garbage_collect_pass(c); | 732 | ret = jffs2_garbage_collect_pass(c); |
| 733 | if (ret) { | 733 | if (ret) { |
| 734 | /* GC failed. Flush it with padding instead */ | 734 | /* GC failed. Flush it with padding instead */ |
| 735 | down(&c->alloc_sem); | 735 | mutex_lock(&c->alloc_sem); |
| 736 | down_write(&c->wbuf_sem); | 736 | down_write(&c->wbuf_sem); |
| 737 | ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING); | 737 | ret = __jffs2_flush_wbuf(c, PAD_ACCOUNTING); |
| 738 | /* retry flushing wbuf in case jffs2_wbuf_recover | 738 | /* retry flushing wbuf in case jffs2_wbuf_recover |
| @@ -742,12 +742,12 @@ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino) | |||
| 742 | up_write(&c->wbuf_sem); | 742 | up_write(&c->wbuf_sem); |
| 743 | break; | 743 | break; |
| 744 | } | 744 | } |
| 745 | down(&c->alloc_sem); | 745 | mutex_lock(&c->alloc_sem); |
| 746 | } | 746 | } |
| 747 | 747 | ||
| 748 | D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() ends...\n")); | 748 | D1(printk(KERN_DEBUG "jffs2_flush_wbuf_gc() ends...\n")); |
| 749 | 749 | ||
| 750 | up(&c->alloc_sem); | 750 | mutex_unlock(&c->alloc_sem); |
| 751 | return ret; | 751 | return ret; |
| 752 | } | 752 | } |
| 753 | 753 | ||
| @@ -1236,12 +1236,24 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) { | |||
| 1236 | if (!c->wbuf) | 1236 | if (!c->wbuf) |
| 1237 | return -ENOMEM; | 1237 | return -ENOMEM; |
| 1238 | 1238 | ||
| 1239 | #ifdef CONFIG_JFFS2_FS_WBUF_VERIFY | ||
| 1240 | c->wbuf_verify = kmalloc(c->wbuf_pagesize, GFP_KERNEL); | ||
| 1241 | if (!c->wbuf_verify) { | ||
| 1242 | kfree(c->oobbuf); | ||
| 1243 | kfree(c->wbuf); | ||
| 1244 | return -ENOMEM; | ||
| 1245 | } | ||
| 1246 | #endif | ||
| 1247 | |||
| 1239 | printk(KERN_INFO "JFFS2 write-buffering enabled buffer (%d) erasesize (%d)\n", c->wbuf_pagesize, c->sector_size); | 1248 | printk(KERN_INFO "JFFS2 write-buffering enabled buffer (%d) erasesize (%d)\n", c->wbuf_pagesize, c->sector_size); |
| 1240 | 1249 | ||
| 1241 | return 0; | 1250 | return 0; |
| 1242 | } | 1251 | } |
| 1243 | 1252 | ||
| 1244 | void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) { | 1253 | void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) { |
| 1254 | #ifdef CONFIG_JFFS2_FS_WBUF_VERIFY | ||
| 1255 | kfree(c->wbuf_verify); | ||
| 1256 | #endif | ||
| 1245 | kfree(c->wbuf); | 1257 | kfree(c->wbuf); |
| 1246 | } | 1258 | } |
| 1247 | 1259 | ||
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 776f13cbf2b5..665fce9797d3 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c | |||
| @@ -137,12 +137,12 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
| 137 | JFFS2_SUMMARY_INODE_SIZE); | 137 | JFFS2_SUMMARY_INODE_SIZE); |
| 138 | } else { | 138 | } else { |
| 139 | /* Locking pain */ | 139 | /* Locking pain */ |
| 140 | up(&f->sem); | 140 | mutex_unlock(&f->sem); |
| 141 | jffs2_complete_reservation(c); | 141 | jffs2_complete_reservation(c); |
| 142 | 142 | ||
| 143 | ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy, | 143 | ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy, |
| 144 | alloc_mode, JFFS2_SUMMARY_INODE_SIZE); | 144 | alloc_mode, JFFS2_SUMMARY_INODE_SIZE); |
| 145 | down(&f->sem); | 145 | mutex_lock(&f->sem); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | if (!ret) { | 148 | if (!ret) { |
| @@ -285,12 +285,12 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
| 285 | JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 285 | JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
| 286 | } else { | 286 | } else { |
| 287 | /* Locking pain */ | 287 | /* Locking pain */ |
| 288 | up(&f->sem); | 288 | mutex_unlock(&f->sem); |
| 289 | jffs2_complete_reservation(c); | 289 | jffs2_complete_reservation(c); |
| 290 | 290 | ||
| 291 | ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy, | 291 | ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy, |
| 292 | alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 292 | alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
| 293 | down(&f->sem); | 293 | mutex_lock(&f->sem); |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | if (!ret) { | 296 | if (!ret) { |
| @@ -353,7 +353,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
| 353 | D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); | 353 | D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); |
| 354 | break; | 354 | break; |
| 355 | } | 355 | } |
| 356 | down(&f->sem); | 356 | mutex_lock(&f->sem); |
| 357 | datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1))); | 357 | datalen = min_t(uint32_t, writelen, PAGE_CACHE_SIZE - (offset & (PAGE_CACHE_SIZE-1))); |
| 358 | cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen); | 358 | cdatalen = min_t(uint32_t, alloclen - sizeof(*ri), datalen); |
| 359 | 359 | ||
| @@ -381,7 +381,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
| 381 | 381 | ||
| 382 | if (IS_ERR(fn)) { | 382 | if (IS_ERR(fn)) { |
| 383 | ret = PTR_ERR(fn); | 383 | ret = PTR_ERR(fn); |
| 384 | up(&f->sem); | 384 | mutex_unlock(&f->sem); |
| 385 | jffs2_complete_reservation(c); | 385 | jffs2_complete_reservation(c); |
| 386 | if (!retried) { | 386 | if (!retried) { |
| 387 | /* Write error to be retried */ | 387 | /* Write error to be retried */ |
| @@ -403,11 +403,11 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
| 403 | jffs2_mark_node_obsolete(c, fn->raw); | 403 | jffs2_mark_node_obsolete(c, fn->raw); |
| 404 | jffs2_free_full_dnode(fn); | 404 | jffs2_free_full_dnode(fn); |
| 405 | 405 | ||
| 406 | up(&f->sem); | 406 | mutex_unlock(&f->sem); |
| 407 | jffs2_complete_reservation(c); | 407 | jffs2_complete_reservation(c); |
| 408 | break; | 408 | break; |
| 409 | } | 409 | } |
| 410 | up(&f->sem); | 410 | mutex_unlock(&f->sem); |
| 411 | jffs2_complete_reservation(c); | 411 | jffs2_complete_reservation(c); |
| 412 | if (!datalen) { | 412 | if (!datalen) { |
| 413 | printk(KERN_WARNING "Eep. We didn't actually write any data in jffs2_write_inode_range()\n"); | 413 | printk(KERN_WARNING "Eep. We didn't actually write any data in jffs2_write_inode_range()\n"); |
| @@ -439,7 +439,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str | |||
| 439 | JFFS2_SUMMARY_INODE_SIZE); | 439 | JFFS2_SUMMARY_INODE_SIZE); |
| 440 | D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); | 440 | D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); |
| 441 | if (ret) { | 441 | if (ret) { |
| 442 | up(&f->sem); | 442 | mutex_unlock(&f->sem); |
| 443 | return ret; | 443 | return ret; |
| 444 | } | 444 | } |
| 445 | 445 | ||
| @@ -454,7 +454,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str | |||
| 454 | if (IS_ERR(fn)) { | 454 | if (IS_ERR(fn)) { |
| 455 | D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n")); | 455 | D1(printk(KERN_DEBUG "jffs2_write_dnode() failed\n")); |
| 456 | /* Eeek. Wave bye bye */ | 456 | /* Eeek. Wave bye bye */ |
| 457 | up(&f->sem); | 457 | mutex_unlock(&f->sem); |
| 458 | jffs2_complete_reservation(c); | 458 | jffs2_complete_reservation(c); |
| 459 | return PTR_ERR(fn); | 459 | return PTR_ERR(fn); |
| 460 | } | 460 | } |
| @@ -463,7 +463,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str | |||
| 463 | */ | 463 | */ |
| 464 | f->metadata = fn; | 464 | f->metadata = fn; |
| 465 | 465 | ||
| 466 | up(&f->sem); | 466 | mutex_unlock(&f->sem); |
| 467 | jffs2_complete_reservation(c); | 467 | jffs2_complete_reservation(c); |
| 468 | 468 | ||
| 469 | ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode); | 469 | ret = jffs2_init_security(&f->vfs_inode, &dir_f->vfs_inode); |
| @@ -489,7 +489,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str | |||
| 489 | return -ENOMEM; | 489 | return -ENOMEM; |
| 490 | } | 490 | } |
| 491 | 491 | ||
| 492 | down(&dir_f->sem); | 492 | mutex_lock(&dir_f->sem); |
| 493 | 493 | ||
| 494 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 494 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
| 495 | rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); | 495 | rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); |
| @@ -513,7 +513,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str | |||
| 513 | /* dirent failed to write. Delete the inode normally | 513 | /* dirent failed to write. Delete the inode normally |
| 514 | as if it were the final unlink() */ | 514 | as if it were the final unlink() */ |
| 515 | jffs2_complete_reservation(c); | 515 | jffs2_complete_reservation(c); |
| 516 | up(&dir_f->sem); | 516 | mutex_unlock(&dir_f->sem); |
| 517 | return PTR_ERR(fd); | 517 | return PTR_ERR(fd); |
| 518 | } | 518 | } |
| 519 | 519 | ||
| @@ -522,7 +522,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str | |||
| 522 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); | 522 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); |
| 523 | 523 | ||
| 524 | jffs2_complete_reservation(c); | 524 | jffs2_complete_reservation(c); |
| 525 | up(&dir_f->sem); | 525 | mutex_unlock(&dir_f->sem); |
| 526 | 526 | ||
| 527 | return 0; | 527 | return 0; |
| 528 | } | 528 | } |
| @@ -551,7 +551,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, | |||
| 551 | return ret; | 551 | return ret; |
| 552 | } | 552 | } |
| 553 | 553 | ||
| 554 | down(&dir_f->sem); | 554 | mutex_lock(&dir_f->sem); |
| 555 | 555 | ||
| 556 | /* Build a deletion node */ | 556 | /* Build a deletion node */ |
| 557 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 557 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
| @@ -574,21 +574,21 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, | |||
| 574 | 574 | ||
| 575 | if (IS_ERR(fd)) { | 575 | if (IS_ERR(fd)) { |
| 576 | jffs2_complete_reservation(c); | 576 | jffs2_complete_reservation(c); |
| 577 | up(&dir_f->sem); | 577 | mutex_unlock(&dir_f->sem); |
| 578 | return PTR_ERR(fd); | 578 | return PTR_ERR(fd); |
| 579 | } | 579 | } |
| 580 | 580 | ||
| 581 | /* File it. This will mark the old one obsolete. */ | 581 | /* File it. This will mark the old one obsolete. */ |
| 582 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); | 582 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); |
| 583 | up(&dir_f->sem); | 583 | mutex_unlock(&dir_f->sem); |
| 584 | } else { | 584 | } else { |
| 585 | struct jffs2_full_dirent *fd = dir_f->dents; | ||
| 586 | uint32_t nhash = full_name_hash(name, namelen); | 585 | uint32_t nhash = full_name_hash(name, namelen); |
| 587 | 586 | ||
| 587 | fd = dir_f->dents; | ||
| 588 | /* We don't actually want to reserve any space, but we do | 588 | /* We don't actually want to reserve any space, but we do |
| 589 | want to be holding the alloc_sem when we write to flash */ | 589 | want to be holding the alloc_sem when we write to flash */ |
| 590 | down(&c->alloc_sem); | 590 | mutex_lock(&c->alloc_sem); |
| 591 | down(&dir_f->sem); | 591 | mutex_lock(&dir_f->sem); |
| 592 | 592 | ||
| 593 | for (fd = dir_f->dents; fd; fd = fd->next) { | 593 | for (fd = dir_f->dents; fd; fd = fd->next) { |
| 594 | if (fd->nhash == nhash && | 594 | if (fd->nhash == nhash && |
| @@ -607,7 +607,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, | |||
| 607 | break; | 607 | break; |
| 608 | } | 608 | } |
| 609 | } | 609 | } |
| 610 | up(&dir_f->sem); | 610 | mutex_unlock(&dir_f->sem); |
| 611 | } | 611 | } |
| 612 | 612 | ||
| 613 | /* dead_f is NULL if this was a rename not a real unlink */ | 613 | /* dead_f is NULL if this was a rename not a real unlink */ |
| @@ -615,7 +615,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, | |||
| 615 | pointing to an inode which didn't exist. */ | 615 | pointing to an inode which didn't exist. */ |
| 616 | if (dead_f && dead_f->inocache) { | 616 | if (dead_f && dead_f->inocache) { |
| 617 | 617 | ||
| 618 | down(&dead_f->sem); | 618 | mutex_lock(&dead_f->sem); |
| 619 | 619 | ||
| 620 | if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) { | 620 | if (S_ISDIR(OFNI_EDONI_2SFFJ(dead_f)->i_mode)) { |
| 621 | while (dead_f->dents) { | 621 | while (dead_f->dents) { |
| @@ -639,7 +639,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, | |||
| 639 | 639 | ||
| 640 | dead_f->inocache->nlink--; | 640 | dead_f->inocache->nlink--; |
| 641 | /* NB: Caller must set inode nlink if appropriate */ | 641 | /* NB: Caller must set inode nlink if appropriate */ |
| 642 | up(&dead_f->sem); | 642 | mutex_unlock(&dead_f->sem); |
| 643 | } | 643 | } |
| 644 | 644 | ||
| 645 | jffs2_complete_reservation(c); | 645 | jffs2_complete_reservation(c); |
| @@ -666,7 +666,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint | |||
| 666 | return ret; | 666 | return ret; |
| 667 | } | 667 | } |
| 668 | 668 | ||
| 669 | down(&dir_f->sem); | 669 | mutex_lock(&dir_f->sem); |
| 670 | 670 | ||
| 671 | /* Build a deletion node */ | 671 | /* Build a deletion node */ |
| 672 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 672 | rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
| @@ -691,7 +691,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint | |||
| 691 | 691 | ||
| 692 | if (IS_ERR(fd)) { | 692 | if (IS_ERR(fd)) { |
| 693 | jffs2_complete_reservation(c); | 693 | jffs2_complete_reservation(c); |
| 694 | up(&dir_f->sem); | 694 | mutex_unlock(&dir_f->sem); |
| 695 | return PTR_ERR(fd); | 695 | return PTR_ERR(fd); |
| 696 | } | 696 | } |
| 697 | 697 | ||
| @@ -699,7 +699,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint | |||
| 699 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); | 699 | jffs2_add_fd_to_list(c, fd, &dir_f->dents); |
| 700 | 700 | ||
| 701 | jffs2_complete_reservation(c); | 701 | jffs2_complete_reservation(c); |
| 702 | up(&dir_f->sem); | 702 | mutex_unlock(&dir_f->sem); |
| 703 | 703 | ||
| 704 | return 0; | 704 | return 0; |
| 705 | } | 705 | } |
diff --git a/fs/lockd/svclock.c b/fs/lockd/svclock.c index 1f122c1940af..4d81553d2948 100644 --- a/fs/lockd/svclock.c +++ b/fs/lockd/svclock.c | |||
| @@ -632,7 +632,7 @@ nlmsvc_update_deferred_block(struct nlm_block *block, struct file_lock *conf, | |||
| 632 | block->b_flags |= B_TIMED_OUT; | 632 | block->b_flags |= B_TIMED_OUT; |
| 633 | if (conf) { | 633 | if (conf) { |
| 634 | if (block->b_fl) | 634 | if (block->b_fl) |
| 635 | locks_copy_lock(block->b_fl, conf); | 635 | __locks_copy_lock(block->b_fl, conf); |
| 636 | } | 636 | } |
| 637 | } | 637 | } |
| 638 | 638 | ||
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c index dbbefbcd6712..d1c48b539df8 100644 --- a/fs/lockd/svcsubs.c +++ b/fs/lockd/svcsubs.c | |||
| @@ -18,6 +18,8 @@ | |||
| 18 | #include <linux/lockd/lockd.h> | 18 | #include <linux/lockd/lockd.h> |
| 19 | #include <linux/lockd/share.h> | 19 | #include <linux/lockd/share.h> |
| 20 | #include <linux/lockd/sm_inter.h> | 20 | #include <linux/lockd/sm_inter.h> |
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/mount.h> | ||
| 21 | 23 | ||
| 22 | #define NLMDBG_FACILITY NLMDBG_SVCSUBS | 24 | #define NLMDBG_FACILITY NLMDBG_SVCSUBS |
| 23 | 25 | ||
| @@ -194,6 +196,12 @@ again: | |||
| 194 | return 0; | 196 | return 0; |
| 195 | } | 197 | } |
| 196 | 198 | ||
| 199 | static int | ||
| 200 | nlmsvc_always_match(void *dummy1, struct nlm_host *dummy2) | ||
| 201 | { | ||
| 202 | return 1; | ||
| 203 | } | ||
| 204 | |||
| 197 | /* | 205 | /* |
| 198 | * Inspect a single file | 206 | * Inspect a single file |
| 199 | */ | 207 | */ |
| @@ -230,7 +238,8 @@ nlm_file_inuse(struct nlm_file *file) | |||
| 230 | * Loop over all files in the file table. | 238 | * Loop over all files in the file table. |
| 231 | */ | 239 | */ |
| 232 | static int | 240 | static int |
| 233 | nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match) | 241 | nlm_traverse_files(void *data, nlm_host_match_fn_t match, |
| 242 | int (*is_failover_file)(void *data, struct nlm_file *file)) | ||
| 234 | { | 243 | { |
| 235 | struct hlist_node *pos, *next; | 244 | struct hlist_node *pos, *next; |
| 236 | struct nlm_file *file; | 245 | struct nlm_file *file; |
| @@ -239,12 +248,14 @@ nlm_traverse_files(struct nlm_host *host, nlm_host_match_fn_t match) | |||
| 239 | mutex_lock(&nlm_file_mutex); | 248 | mutex_lock(&nlm_file_mutex); |
| 240 | for (i = 0; i < FILE_NRHASH; i++) { | 249 | for (i = 0; i < FILE_NRHASH; i++) { |
| 241 | hlist_for_each_entry_safe(file, pos, next, &nlm_files[i], f_list) { | 250 | hlist_for_each_entry_safe(file, pos, next, &nlm_files[i], f_list) { |
| 251 | if (is_failover_file && !is_failover_file(data, file)) | ||
| 252 | continue; | ||
| 242 | file->f_count++; | 253 | file->f_count++; |
| 243 | mutex_unlock(&nlm_file_mutex); | 254 | mutex_unlock(&nlm_file_mutex); |
| 244 | 255 | ||
| 245 | /* Traverse locks, blocks and shares of this file | 256 | /* Traverse locks, blocks and shares of this file |
| 246 | * and update file->f_locks count */ | 257 | * and update file->f_locks count */ |
| 247 | if (nlm_inspect_file(host, file, match)) | 258 | if (nlm_inspect_file(data, file, match)) |
| 248 | ret = 1; | 259 | ret = 1; |
| 249 | 260 | ||
| 250 | mutex_lock(&nlm_file_mutex); | 261 | mutex_lock(&nlm_file_mutex); |
| @@ -303,21 +314,27 @@ nlm_release_file(struct nlm_file *file) | |||
| 303 | * Used by nlmsvc_invalidate_all | 314 | * Used by nlmsvc_invalidate_all |
| 304 | */ | 315 | */ |
| 305 | static int | 316 | static int |
| 306 | nlmsvc_mark_host(struct nlm_host *host, struct nlm_host *dummy) | 317 | nlmsvc_mark_host(void *data, struct nlm_host *dummy) |
| 307 | { | 318 | { |
| 319 | struct nlm_host *host = data; | ||
| 320 | |||
| 308 | host->h_inuse = 1; | 321 | host->h_inuse = 1; |
| 309 | return 0; | 322 | return 0; |
| 310 | } | 323 | } |
| 311 | 324 | ||
| 312 | static int | 325 | static int |
| 313 | nlmsvc_same_host(struct nlm_host *host, struct nlm_host *other) | 326 | nlmsvc_same_host(void *data, struct nlm_host *other) |
| 314 | { | 327 | { |
| 328 | struct nlm_host *host = data; | ||
| 329 | |||
| 315 | return host == other; | 330 | return host == other; |
| 316 | } | 331 | } |
| 317 | 332 | ||
| 318 | static int | 333 | static int |
| 319 | nlmsvc_is_client(struct nlm_host *host, struct nlm_host *dummy) | 334 | nlmsvc_is_client(void *data, struct nlm_host *dummy) |
| 320 | { | 335 | { |
| 336 | struct nlm_host *host = data; | ||
| 337 | |||
| 321 | if (host->h_server) { | 338 | if (host->h_server) { |
| 322 | /* we are destroying locks even though the client | 339 | /* we are destroying locks even though the client |
| 323 | * hasn't asked us too, so don't unmonitor the | 340 | * hasn't asked us too, so don't unmonitor the |
| @@ -337,7 +354,7 @@ void | |||
| 337 | nlmsvc_mark_resources(void) | 354 | nlmsvc_mark_resources(void) |
| 338 | { | 355 | { |
| 339 | dprintk("lockd: nlmsvc_mark_resources\n"); | 356 | dprintk("lockd: nlmsvc_mark_resources\n"); |
| 340 | nlm_traverse_files(NULL, nlmsvc_mark_host); | 357 | nlm_traverse_files(NULL, nlmsvc_mark_host, NULL); |
| 341 | } | 358 | } |
| 342 | 359 | ||
| 343 | /* | 360 | /* |
| @@ -348,7 +365,7 @@ nlmsvc_free_host_resources(struct nlm_host *host) | |||
| 348 | { | 365 | { |
| 349 | dprintk("lockd: nlmsvc_free_host_resources\n"); | 366 | dprintk("lockd: nlmsvc_free_host_resources\n"); |
| 350 | 367 | ||
| 351 | if (nlm_traverse_files(host, nlmsvc_same_host)) { | 368 | if (nlm_traverse_files(host, nlmsvc_same_host, NULL)) { |
| 352 | printk(KERN_WARNING | 369 | printk(KERN_WARNING |
| 353 | "lockd: couldn't remove all locks held by %s\n", | 370 | "lockd: couldn't remove all locks held by %s\n", |
| 354 | host->h_name); | 371 | host->h_name); |
| @@ -368,5 +385,41 @@ nlmsvc_invalidate_all(void) | |||
| 368 | * turn, which is about as inefficient as it gets. | 385 | * turn, which is about as inefficient as it gets. |
| 369 | * Now we just do it once in nlm_traverse_files. | 386 | * Now we just do it once in nlm_traverse_files. |
| 370 | */ | 387 | */ |
| 371 | nlm_traverse_files(NULL, nlmsvc_is_client); | 388 | nlm_traverse_files(NULL, nlmsvc_is_client, NULL); |
| 389 | } | ||
| 390 | |||
| 391 | static int | ||
| 392 | nlmsvc_match_sb(void *datap, struct nlm_file *file) | ||
| 393 | { | ||
| 394 | struct super_block *sb = datap; | ||
| 395 | |||
| 396 | return sb == file->f_file->f_path.mnt->mnt_sb; | ||
| 397 | } | ||
| 398 | |||
| 399 | int | ||
| 400 | nlmsvc_unlock_all_by_sb(struct super_block *sb) | ||
| 401 | { | ||
| 402 | int ret; | ||
| 403 | |||
| 404 | ret = nlm_traverse_files(sb, nlmsvc_always_match, nlmsvc_match_sb); | ||
| 405 | return ret ? -EIO : 0; | ||
| 406 | } | ||
| 407 | EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_sb); | ||
| 408 | |||
| 409 | static int | ||
| 410 | nlmsvc_match_ip(void *datap, struct nlm_host *host) | ||
| 411 | { | ||
| 412 | __be32 *server_addr = datap; | ||
| 413 | |||
| 414 | return host->h_saddr.sin_addr.s_addr == *server_addr; | ||
| 415 | } | ||
| 416 | |||
| 417 | int | ||
| 418 | nlmsvc_unlock_all_by_ip(__be32 server_addr) | ||
| 419 | { | ||
| 420 | int ret; | ||
| 421 | ret = nlm_traverse_files(&server_addr, nlmsvc_match_ip, NULL); | ||
| 422 | return ret ? -EIO : 0; | ||
| 423 | |||
| 372 | } | 424 | } |
| 425 | EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_ip); | ||
diff --git a/fs/locks.c b/fs/locks.c index 592faadbcec1..e1ea2fe03681 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
| @@ -224,7 +224,7 @@ static void locks_copy_private(struct file_lock *new, struct file_lock *fl) | |||
| 224 | /* | 224 | /* |
| 225 | * Initialize a new lock from an existing file_lock structure. | 225 | * Initialize a new lock from an existing file_lock structure. |
| 226 | */ | 226 | */ |
| 227 | static void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl) | 227 | void __locks_copy_lock(struct file_lock *new, const struct file_lock *fl) |
| 228 | { | 228 | { |
| 229 | new->fl_owner = fl->fl_owner; | 229 | new->fl_owner = fl->fl_owner; |
| 230 | new->fl_pid = fl->fl_pid; | 230 | new->fl_pid = fl->fl_pid; |
| @@ -833,7 +833,7 @@ static int __posix_lock_file(struct inode *inode, struct file_lock *request, str | |||
| 833 | if (!posix_locks_conflict(request, fl)) | 833 | if (!posix_locks_conflict(request, fl)) |
| 834 | continue; | 834 | continue; |
| 835 | if (conflock) | 835 | if (conflock) |
| 836 | locks_copy_lock(conflock, fl); | 836 | __locks_copy_lock(conflock, fl); |
| 837 | error = -EAGAIN; | 837 | error = -EAGAIN; |
| 838 | if (!(request->fl_flags & FL_SLEEP)) | 838 | if (!(request->fl_flags & FL_SLEEP)) |
| 839 | goto out; | 839 | goto out; |
| @@ -1367,18 +1367,20 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp) | |||
| 1367 | 1367 | ||
| 1368 | lease = *flp; | 1368 | lease = *flp; |
| 1369 | 1369 | ||
| 1370 | error = -EAGAIN; | 1370 | if (arg != F_UNLCK) { |
| 1371 | if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) | 1371 | error = -ENOMEM; |
| 1372 | goto out; | 1372 | new_fl = locks_alloc_lock(); |
| 1373 | if ((arg == F_WRLCK) | 1373 | if (new_fl == NULL) |
| 1374 | && ((atomic_read(&dentry->d_count) > 1) | 1374 | goto out; |
| 1375 | || (atomic_read(&inode->i_count) > 1))) | ||
| 1376 | goto out; | ||
| 1377 | 1375 | ||
| 1378 | error = -ENOMEM; | 1376 | error = -EAGAIN; |
| 1379 | new_fl = locks_alloc_lock(); | 1377 | if ((arg == F_RDLCK) && (atomic_read(&inode->i_writecount) > 0)) |
| 1380 | if (new_fl == NULL) | 1378 | goto out; |
| 1381 | goto out; | 1379 | if ((arg == F_WRLCK) |
| 1380 | && ((atomic_read(&dentry->d_count) > 1) | ||
| 1381 | || (atomic_read(&inode->i_count) > 1))) | ||
| 1382 | goto out; | ||
| 1383 | } | ||
| 1382 | 1384 | ||
| 1383 | /* | 1385 | /* |
| 1384 | * At this point, we know that if there is an exclusive | 1386 | * At this point, we know that if there is an exclusive |
| @@ -1404,6 +1406,7 @@ int generic_setlease(struct file *filp, long arg, struct file_lock **flp) | |||
| 1404 | rdlease_count++; | 1406 | rdlease_count++; |
| 1405 | } | 1407 | } |
| 1406 | 1408 | ||
| 1409 | error = -EAGAIN; | ||
| 1407 | if ((arg == F_RDLCK && (wrlease_count > 0)) || | 1410 | if ((arg == F_RDLCK && (wrlease_count > 0)) || |
| 1408 | (arg == F_WRLCK && ((rdlease_count + wrlease_count) > 0))) | 1411 | (arg == F_WRLCK && ((rdlease_count + wrlease_count) > 0))) |
| 1409 | goto out; | 1412 | goto out; |
| @@ -1490,8 +1493,7 @@ EXPORT_SYMBOL_GPL(vfs_setlease); | |||
| 1490 | int fcntl_setlease(unsigned int fd, struct file *filp, long arg) | 1493 | int fcntl_setlease(unsigned int fd, struct file *filp, long arg) |
| 1491 | { | 1494 | { |
| 1492 | struct file_lock fl, *flp = &fl; | 1495 | struct file_lock fl, *flp = &fl; |
| 1493 | struct dentry *dentry = filp->f_path.dentry; | 1496 | struct inode *inode = filp->f_path.dentry->d_inode; |
| 1494 | struct inode *inode = dentry->d_inode; | ||
| 1495 | int error; | 1497 | int error; |
| 1496 | 1498 | ||
| 1497 | locks_init_lock(&fl); | 1499 | locks_init_lock(&fl); |
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 55dfdd71f1b0..8799b8708188 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c | |||
| @@ -2712,9 +2712,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
| 2712 | * Note: locks.c uses the BKL to protect the inode's lock list. | 2712 | * Note: locks.c uses the BKL to protect the inode's lock list. |
| 2713 | */ | 2713 | */ |
| 2714 | 2714 | ||
| 2715 | /* XXX?: Just to divert the locks_release_private at the start of | ||
| 2716 | * locks_copy_lock: */ | ||
| 2717 | locks_init_lock(&conflock); | ||
| 2718 | err = vfs_lock_file(filp, cmd, &file_lock, &conflock); | 2715 | err = vfs_lock_file(filp, cmd, &file_lock, &conflock); |
| 2719 | switch (-err) { | 2716 | switch (-err) { |
| 2720 | case 0: /* success! */ | 2717 | case 0: /* success! */ |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 1ba7ad981935..c513bbdf2d36 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
| @@ -376,20 +376,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia | |||
| 376 | goto xdr_error; | 376 | goto xdr_error; |
| 377 | } | 377 | } |
| 378 | } | 378 | } |
| 379 | if (bmval[1] & FATTR4_WORD1_TIME_METADATA) { | ||
| 380 | /* We require the high 32 bits of 'seconds' to be 0, and we ignore | ||
| 381 | all 32 bits of 'nseconds'. */ | ||
| 382 | READ_BUF(12); | ||
| 383 | len += 12; | ||
| 384 | READ32(dummy32); | ||
| 385 | if (dummy32) | ||
| 386 | return nfserr_inval; | ||
| 387 | READ32(iattr->ia_ctime.tv_sec); | ||
| 388 | READ32(iattr->ia_ctime.tv_nsec); | ||
| 389 | if (iattr->ia_ctime.tv_nsec >= (u32)1000000000) | ||
| 390 | return nfserr_inval; | ||
| 391 | iattr->ia_valid |= ATTR_CTIME; | ||
| 392 | } | ||
| 393 | if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) { | 379 | if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) { |
| 394 | READ_BUF(4); | 380 | READ_BUF(4); |
| 395 | len += 4; | 381 | len += 4; |
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 613bcb8171a5..42f3820ee8f5 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
| 23 | #include <linux/pagemap.h> | 23 | #include <linux/pagemap.h> |
| 24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
| 25 | #include <linux/inet.h> | ||
| 25 | #include <linux/string.h> | 26 | #include <linux/string.h> |
| 26 | #include <linux/smp_lock.h> | 27 | #include <linux/smp_lock.h> |
| 27 | #include <linux/ctype.h> | 28 | #include <linux/ctype.h> |
| @@ -35,6 +36,7 @@ | |||
| 35 | #include <linux/nfsd/cache.h> | 36 | #include <linux/nfsd/cache.h> |
| 36 | #include <linux/nfsd/xdr.h> | 37 | #include <linux/nfsd/xdr.h> |
| 37 | #include <linux/nfsd/syscall.h> | 38 | #include <linux/nfsd/syscall.h> |
| 39 | #include <linux/lockd/lockd.h> | ||
| 38 | 40 | ||
| 39 | #include <asm/uaccess.h> | 41 | #include <asm/uaccess.h> |
| 40 | #include <net/ipv6.h> | 42 | #include <net/ipv6.h> |
| @@ -53,6 +55,8 @@ enum { | |||
| 53 | NFSD_Getfs, | 55 | NFSD_Getfs, |
| 54 | NFSD_List, | 56 | NFSD_List, |
| 55 | NFSD_Fh, | 57 | NFSD_Fh, |
| 58 | NFSD_FO_UnlockIP, | ||
| 59 | NFSD_FO_UnlockFS, | ||
| 56 | NFSD_Threads, | 60 | NFSD_Threads, |
| 57 | NFSD_Pool_Threads, | 61 | NFSD_Pool_Threads, |
| 58 | NFSD_Versions, | 62 | NFSD_Versions, |
| @@ -89,6 +93,9 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size); | |||
| 89 | static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); | 93 | static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); |
| 90 | #endif | 94 | #endif |
| 91 | 95 | ||
| 96 | static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size); | ||
| 97 | static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size); | ||
| 98 | |||
| 92 | static ssize_t (*write_op[])(struct file *, char *, size_t) = { | 99 | static ssize_t (*write_op[])(struct file *, char *, size_t) = { |
| 93 | [NFSD_Svc] = write_svc, | 100 | [NFSD_Svc] = write_svc, |
| 94 | [NFSD_Add] = write_add, | 101 | [NFSD_Add] = write_add, |
| @@ -98,6 +105,8 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { | |||
| 98 | [NFSD_Getfd] = write_getfd, | 105 | [NFSD_Getfd] = write_getfd, |
| 99 | [NFSD_Getfs] = write_getfs, | 106 | [NFSD_Getfs] = write_getfs, |
| 100 | [NFSD_Fh] = write_filehandle, | 107 | [NFSD_Fh] = write_filehandle, |
| 108 | [NFSD_FO_UnlockIP] = failover_unlock_ip, | ||
| 109 | [NFSD_FO_UnlockFS] = failover_unlock_fs, | ||
| 101 | [NFSD_Threads] = write_threads, | 110 | [NFSD_Threads] = write_threads, |
| 102 | [NFSD_Pool_Threads] = write_pool_threads, | 111 | [NFSD_Pool_Threads] = write_pool_threads, |
| 103 | [NFSD_Versions] = write_versions, | 112 | [NFSD_Versions] = write_versions, |
| @@ -298,6 +307,58 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size) | |||
| 298 | return err; | 307 | return err; |
| 299 | } | 308 | } |
| 300 | 309 | ||
| 310 | static ssize_t failover_unlock_ip(struct file *file, char *buf, size_t size) | ||
| 311 | { | ||
| 312 | __be32 server_ip; | ||
| 313 | char *fo_path, c; | ||
| 314 | int b1, b2, b3, b4; | ||
| 315 | |||
| 316 | /* sanity check */ | ||
| 317 | if (size == 0) | ||
| 318 | return -EINVAL; | ||
| 319 | |||
| 320 | if (buf[size-1] != '\n') | ||
| 321 | return -EINVAL; | ||
| 322 | |||
| 323 | fo_path = buf; | ||
| 324 | if (qword_get(&buf, fo_path, size) < 0) | ||
| 325 | return -EINVAL; | ||
| 326 | |||
| 327 | /* get ipv4 address */ | ||
| 328 | if (sscanf(fo_path, "%u.%u.%u.%u%c", &b1, &b2, &b3, &b4, &c) != 4) | ||
| 329 | return -EINVAL; | ||
| 330 | server_ip = htonl((((((b1<<8)|b2)<<8)|b3)<<8)|b4); | ||
| 331 | |||
| 332 | return nlmsvc_unlock_all_by_ip(server_ip); | ||
| 333 | } | ||
| 334 | |||
| 335 | static ssize_t failover_unlock_fs(struct file *file, char *buf, size_t size) | ||
| 336 | { | ||
| 337 | struct nameidata nd; | ||
| 338 | char *fo_path; | ||
| 339 | int error; | ||
| 340 | |||
| 341 | /* sanity check */ | ||
| 342 | if (size == 0) | ||
| 343 | return -EINVAL; | ||
| 344 | |||
| 345 | if (buf[size-1] != '\n') | ||
| 346 | return -EINVAL; | ||
| 347 | |||
| 348 | fo_path = buf; | ||
| 349 | if (qword_get(&buf, fo_path, size) < 0) | ||
| 350 | return -EINVAL; | ||
| 351 | |||
| 352 | error = path_lookup(fo_path, 0, &nd); | ||
| 353 | if (error) | ||
| 354 | return error; | ||
| 355 | |||
| 356 | error = nlmsvc_unlock_all_by_sb(nd.path.mnt->mnt_sb); | ||
| 357 | |||
| 358 | path_put(&nd.path); | ||
| 359 | return error; | ||
| 360 | } | ||
| 361 | |||
| 301 | static ssize_t write_filehandle(struct file *file, char *buf, size_t size) | 362 | static ssize_t write_filehandle(struct file *file, char *buf, size_t size) |
| 302 | { | 363 | { |
| 303 | /* request is: | 364 | /* request is: |
| @@ -700,6 +761,10 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) | |||
| 700 | [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR}, | 761 | [NFSD_Getfd] = {".getfd", &transaction_ops, S_IWUSR|S_IRUSR}, |
| 701 | [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR}, | 762 | [NFSD_Getfs] = {".getfs", &transaction_ops, S_IWUSR|S_IRUSR}, |
| 702 | [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, | 763 | [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, |
| 764 | [NFSD_FO_UnlockIP] = {"unlock_ip", | ||
| 765 | &transaction_ops, S_IWUSR|S_IRUSR}, | ||
| 766 | [NFSD_FO_UnlockFS] = {"unlock_filesystem", | ||
| 767 | &transaction_ops, S_IWUSR|S_IRUSR}, | ||
| 703 | [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, | 768 | [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, |
| 704 | [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, | 769 | [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, |
| 705 | [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR}, | 770 | [NFSD_Pool_Threads] = {"pool_threads", &transaction_ops, S_IWUSR|S_IRUSR}, |
diff --git a/include/asm-arm/arch-pxa/pxa3xx_nand.h b/include/asm-arm/arch-pxa/pxa3xx_nand.h new file mode 100644 index 000000000000..81a8937486cb --- /dev/null +++ b/include/asm-arm/arch-pxa/pxa3xx_nand.h | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | #ifndef __ASM_ARCH_PXA3XX_NAND_H | ||
| 2 | #define __ASM_ARCH_PXA3XX_NAND_H | ||
| 3 | |||
| 4 | #include <linux/mtd/mtd.h> | ||
| 5 | #include <linux/mtd/partitions.h> | ||
| 6 | |||
| 7 | struct pxa3xx_nand_platform_data { | ||
| 8 | |||
| 9 | /* the data flash bus is shared between the Static Memory | ||
| 10 | * Controller and the Data Flash Controller, the arbiter | ||
| 11 | * controls the ownership of the bus | ||
| 12 | */ | ||
| 13 | int enable_arbiter; | ||
| 14 | |||
| 15 | struct mtd_partition *parts; | ||
| 16 | unsigned int nr_parts; | ||
| 17 | }; | ||
| 18 | #endif /* __ASM_ARCH_PXA3XX_NAND_H */ | ||
diff --git a/include/asm-arm/plat-s3c/nand.h b/include/asm-arm/plat-s3c/nand.h index 8816f7f9cee1..ad6bbe90616e 100644 --- a/include/asm-arm/plat-s3c/nand.h +++ b/include/asm-arm/plat-s3c/nand.h | |||
| @@ -22,11 +22,14 @@ | |||
| 22 | */ | 22 | */ |
| 23 | 23 | ||
| 24 | struct s3c2410_nand_set { | 24 | struct s3c2410_nand_set { |
| 25 | unsigned int disable_ecc : 1; | ||
| 26 | |||
| 25 | int nr_chips; | 27 | int nr_chips; |
| 26 | int nr_partitions; | 28 | int nr_partitions; |
| 27 | char *name; | 29 | char *name; |
| 28 | int *nr_map; | 30 | int *nr_map; |
| 29 | struct mtd_partition *partitions; | 31 | struct mtd_partition *partitions; |
| 32 | struct nand_ecclayout *ecc_layout; | ||
| 30 | }; | 33 | }; |
| 31 | 34 | ||
| 32 | struct s3c2410_platform_nand { | 35 | struct s3c2410_platform_nand { |
| @@ -36,6 +39,8 @@ struct s3c2410_platform_nand { | |||
| 36 | int twrph0; /* active time for nWE/nOE */ | 39 | int twrph0; /* active time for nWE/nOE */ |
| 37 | int twrph1; /* time for release CLE/ALE from nWE/nOE inactive */ | 40 | int twrph1; /* time for release CLE/ALE from nWE/nOE inactive */ |
| 38 | 41 | ||
| 42 | unsigned int ignore_unset_ecc : 1; | ||
| 43 | |||
| 39 | int nr_sets; | 44 | int nr_sets; |
| 40 | struct s3c2410_nand_set *sets; | 45 | struct s3c2410_nand_set *sets; |
| 41 | 46 | ||
diff --git a/include/asm-x86/fixmap.h b/include/asm-x86/fixmap.h index 382eb271a892..5bd206973dca 100644 --- a/include/asm-x86/fixmap.h +++ b/include/asm-x86/fixmap.h | |||
| @@ -1,5 +1,13 @@ | |||
| 1 | #ifndef _ASM_FIXMAP_H | ||
| 2 | #define _ASM_FIXMAP_H | ||
| 3 | |||
| 1 | #ifdef CONFIG_X86_32 | 4 | #ifdef CONFIG_X86_32 |
| 2 | # include "fixmap_32.h" | 5 | # include "fixmap_32.h" |
| 3 | #else | 6 | #else |
| 4 | # include "fixmap_64.h" | 7 | # include "fixmap_64.h" |
| 5 | #endif | 8 | #endif |
| 9 | |||
| 10 | #define clear_fixmap(idx) \ | ||
| 11 | __set_fixmap(idx, 0, __pgprot(0)) | ||
| 12 | |||
| 13 | #endif | ||
diff --git a/include/asm-x86/fixmap_32.h b/include/asm-x86/fixmap_32.h index eb1665125c44..4b96148e90c1 100644 --- a/include/asm-x86/fixmap_32.h +++ b/include/asm-x86/fixmap_32.h | |||
| @@ -10,8 +10,8 @@ | |||
| 10 | * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 | 10 | * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999 |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #ifndef _ASM_FIXMAP_H | 13 | #ifndef _ASM_FIXMAP_32_H |
| 14 | #define _ASM_FIXMAP_H | 14 | #define _ASM_FIXMAP_32_H |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | /* used by vmalloc.c, vsyscall.lds.S. | 17 | /* used by vmalloc.c, vsyscall.lds.S. |
| @@ -121,9 +121,6 @@ extern void reserve_top_address(unsigned long reserve); | |||
| 121 | #define set_fixmap_nocache(idx, phys) \ | 121 | #define set_fixmap_nocache(idx, phys) \ |
| 122 | __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE) | 122 | __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE) |
| 123 | 123 | ||
| 124 | #define clear_fixmap(idx) \ | ||
| 125 | __set_fixmap(idx, 0, __pgprot(0)) | ||
| 126 | |||
| 127 | #define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP) | 124 | #define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP) |
| 128 | 125 | ||
| 129 | #define __FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT) | 126 | #define __FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT) |
diff --git a/include/asm-x86/fixmap_64.h b/include/asm-x86/fixmap_64.h index f3d76858c0e6..355d26a75a82 100644 --- a/include/asm-x86/fixmap_64.h +++ b/include/asm-x86/fixmap_64.h | |||
| @@ -8,8 +8,8 @@ | |||
| 8 | * Copyright (C) 1998 Ingo Molnar | 8 | * Copyright (C) 1998 Ingo Molnar |
| 9 | */ | 9 | */ |
| 10 | 10 | ||
| 11 | #ifndef _ASM_FIXMAP_H | 11 | #ifndef _ASM_FIXMAP_64_H |
| 12 | #define _ASM_FIXMAP_H | 12 | #define _ASM_FIXMAP_64_H |
| 13 | 13 | ||
| 14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 15 | #include <asm/apicdef.h> | 15 | #include <asm/apicdef.h> |
diff --git a/include/linux/fs.h b/include/linux/fs.h index cc2be2cf7d41..6556f2f967e5 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -973,6 +973,7 @@ extern int do_sync_mapping_range(struct address_space *mapping, loff_t offset, | |||
| 973 | /* fs/locks.c */ | 973 | /* fs/locks.c */ |
| 974 | extern void locks_init_lock(struct file_lock *); | 974 | extern void locks_init_lock(struct file_lock *); |
| 975 | extern void locks_copy_lock(struct file_lock *, struct file_lock *); | 975 | extern void locks_copy_lock(struct file_lock *, struct file_lock *); |
| 976 | extern void __locks_copy_lock(struct file_lock *, const struct file_lock *); | ||
| 976 | extern void locks_remove_posix(struct file *, fl_owner_t); | 977 | extern void locks_remove_posix(struct file *, fl_owner_t); |
| 977 | extern void locks_remove_flock(struct file *); | 978 | extern void locks_remove_flock(struct file *); |
| 978 | extern void posix_test_lock(struct file *, struct file_lock *); | 979 | extern void posix_test_lock(struct file *, struct file_lock *); |
diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 94649a8da014..102d928f7206 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h | |||
| @@ -194,7 +194,7 @@ void nsm_release(struct nsm_handle *); | |||
| 194 | * This is used in garbage collection and resource reclaim | 194 | * This is used in garbage collection and resource reclaim |
| 195 | * A return value != 0 means destroy the lock/block/share | 195 | * A return value != 0 means destroy the lock/block/share |
| 196 | */ | 196 | */ |
| 197 | typedef int (*nlm_host_match_fn_t)(struct nlm_host *cur, struct nlm_host *ref); | 197 | typedef int (*nlm_host_match_fn_t)(void *cur, struct nlm_host *ref); |
| 198 | 198 | ||
| 199 | /* | 199 | /* |
| 200 | * Server-side lock handling | 200 | * Server-side lock handling |
| @@ -220,6 +220,12 @@ void nlmsvc_mark_resources(void); | |||
| 220 | void nlmsvc_free_host_resources(struct nlm_host *); | 220 | void nlmsvc_free_host_resources(struct nlm_host *); |
| 221 | void nlmsvc_invalidate_all(void); | 221 | void nlmsvc_invalidate_all(void); |
| 222 | 222 | ||
| 223 | /* | ||
| 224 | * Cluster failover support | ||
| 225 | */ | ||
| 226 | int nlmsvc_unlock_all_by_sb(struct super_block *sb); | ||
| 227 | int nlmsvc_unlock_all_by_ip(__be32 server_addr); | ||
| 228 | |||
| 223 | static inline struct inode *nlmsvc_file_inode(struct nlm_file *file) | 229 | static inline struct inode *nlmsvc_file_inode(struct nlm_file *file) |
| 224 | { | 230 | { |
| 225 | return file->f_file->f_path.dentry->d_inode; | 231 | return file->f_file->f_path.dentry->d_inode; |
diff --git a/include/linux/mtd/inftl.h b/include/linux/mtd/inftl.h index 6977780e548f..85fd041d44ad 100644 --- a/include/linux/mtd/inftl.h +++ b/include/linux/mtd/inftl.h | |||
| @@ -57,6 +57,11 @@ extern char inftlmountrev[]; | |||
| 57 | void INFTL_dumptables(struct INFTLrecord *s); | 57 | void INFTL_dumptables(struct INFTLrecord *s); |
| 58 | void INFTL_dumpVUchains(struct INFTLrecord *s); | 58 | void INFTL_dumpVUchains(struct INFTLrecord *s); |
| 59 | 59 | ||
| 60 | int inftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, | ||
| 61 | size_t *retlen, uint8_t *buf); | ||
| 62 | int inftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, | ||
| 63 | size_t *retlen, uint8_t *buf); | ||
| 64 | |||
| 60 | #endif /* __KERNEL__ */ | 65 | #endif /* __KERNEL__ */ |
| 61 | 66 | ||
| 62 | #endif /* __MTD_INFTL_H__ */ | 67 | #endif /* __MTD_INFTL_H__ */ |
diff --git a/include/linux/mtd/nftl.h b/include/linux/mtd/nftl.h index bcf2fb3fa4a7..001eec50cac6 100644 --- a/include/linux/mtd/nftl.h +++ b/include/linux/mtd/nftl.h | |||
| @@ -43,6 +43,11 @@ struct NFTLrecord { | |||
| 43 | int NFTL_mount(struct NFTLrecord *s); | 43 | int NFTL_mount(struct NFTLrecord *s); |
| 44 | int NFTL_formatblock(struct NFTLrecord *s, int block); | 44 | int NFTL_formatblock(struct NFTLrecord *s, int block); |
| 45 | 45 | ||
| 46 | int nftl_read_oob(struct mtd_info *mtd, loff_t offs, size_t len, | ||
| 47 | size_t *retlen, uint8_t *buf); | ||
| 48 | int nftl_write_oob(struct mtd_info *mtd, loff_t offs, size_t len, | ||
| 49 | size_t *retlen, uint8_t *buf); | ||
| 50 | |||
| 46 | #ifndef NFTL_MAJOR | 51 | #ifndef NFTL_MAJOR |
| 47 | #define NFTL_MAJOR 93 | 52 | #define NFTL_MAJOR 93 |
| 48 | #endif | 53 | #endif |
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index fd0a260e070b..9aa2a9149b58 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h | |||
| @@ -187,4 +187,7 @@ struct onenand_manufacturers { | |||
| 187 | char *name; | 187 | char *name; |
| 188 | }; | 188 | }; |
| 189 | 189 | ||
| 190 | int onenand_bbt_read_oob(struct mtd_info *mtd, loff_t from, | ||
| 191 | struct mtd_oob_ops *ops); | ||
| 192 | |||
| 190 | #endif /* __LINUX_MTD_ONENAND_H */ | 193 | #endif /* __LINUX_MTD_ONENAND_H */ |
diff --git a/include/linux/mtd/plat-ram.h b/include/linux/mtd/plat-ram.h index 9667863bd7e3..0e37ad07bce2 100644 --- a/include/linux/mtd/plat-ram.h +++ b/include/linux/mtd/plat-ram.h | |||
| @@ -21,8 +21,9 @@ | |||
| 21 | #define PLATRAM_RW (1) | 21 | #define PLATRAM_RW (1) |
| 22 | 22 | ||
| 23 | struct platdata_mtd_ram { | 23 | struct platdata_mtd_ram { |
| 24 | char *mapname; | 24 | const char *mapname; |
| 25 | char **probes; | 25 | const char **map_probes; |
| 26 | const char **probes; | ||
| 26 | struct mtd_partition *partitions; | 27 | struct mtd_partition *partitions; |
| 27 | int nr_partitions; | 28 | int nr_partitions; |
| 28 | int bankwidth; | 29 | int bankwidth; |
diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index 21ee440dd3e7..41d30c9c9de6 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h | |||
| @@ -329,7 +329,7 @@ extern struct timeval nfssvc_boot; | |||
| 329 | (FATTR4_WORD0_SIZE | FATTR4_WORD0_ACL ) | 329 | (FATTR4_WORD0_SIZE | FATTR4_WORD0_ACL ) |
| 330 | #define NFSD_WRITEABLE_ATTRS_WORD1 \ | 330 | #define NFSD_WRITEABLE_ATTRS_WORD1 \ |
| 331 | (FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \ | 331 | (FATTR4_WORD1_MODE | FATTR4_WORD1_OWNER | FATTR4_WORD1_OWNER_GROUP \ |
| 332 | | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_METADATA | FATTR4_WORD1_TIME_MODIFY_SET) | 332 | | FATTR4_WORD1_TIME_ACCESS_SET | FATTR4_WORD1_TIME_MODIFY_SET) |
| 333 | 333 | ||
| 334 | #endif /* CONFIG_NFSD_V4 */ | 334 | #endif /* CONFIG_NFSD_V4 */ |
| 335 | 335 | ||
diff --git a/include/linux/phy.h b/include/linux/phy.h index 779cbcd65f62..02df20f085fe 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h | |||
| @@ -379,6 +379,18 @@ struct phy_driver { | |||
| 379 | }; | 379 | }; |
| 380 | #define to_phy_driver(d) container_of(d, struct phy_driver, driver) | 380 | #define to_phy_driver(d) container_of(d, struct phy_driver, driver) |
| 381 | 381 | ||
| 382 | #define PHY_ANY_ID "MATCH ANY PHY" | ||
| 383 | #define PHY_ANY_UID 0xffffffff | ||
| 384 | |||
| 385 | /* A Structure for boards to register fixups with the PHY Lib */ | ||
| 386 | struct phy_fixup { | ||
| 387 | struct list_head list; | ||
| 388 | char bus_id[BUS_ID_SIZE]; | ||
| 389 | u32 phy_uid; | ||
| 390 | u32 phy_uid_mask; | ||
| 391 | int (*run)(struct phy_device *phydev); | ||
| 392 | }; | ||
| 393 | |||
| 382 | int phy_read(struct phy_device *phydev, u16 regnum); | 394 | int phy_read(struct phy_device *phydev, u16 regnum); |
| 383 | int phy_write(struct phy_device *phydev, u16 regnum, u16 val); | 395 | int phy_write(struct phy_device *phydev, u16 regnum, u16 val); |
| 384 | int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id); | 396 | int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id); |
| @@ -386,8 +398,8 @@ struct phy_device* get_phy_device(struct mii_bus *bus, int addr); | |||
| 386 | int phy_clear_interrupt(struct phy_device *phydev); | 398 | int phy_clear_interrupt(struct phy_device *phydev); |
| 387 | int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); | 399 | int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); |
| 388 | struct phy_device * phy_attach(struct net_device *dev, | 400 | struct phy_device * phy_attach(struct net_device *dev, |
| 389 | const char *phy_id, u32 flags, phy_interface_t interface); | 401 | const char *bus_id, u32 flags, phy_interface_t interface); |
| 390 | struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, | 402 | struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, |
| 391 | void (*handler)(struct net_device *), u32 flags, | 403 | void (*handler)(struct net_device *), u32 flags, |
| 392 | phy_interface_t interface); | 404 | phy_interface_t interface); |
| 393 | void phy_disconnect(struct phy_device *phydev); | 405 | void phy_disconnect(struct phy_device *phydev); |
| @@ -427,5 +439,13 @@ void phy_print_status(struct phy_device *phydev); | |||
| 427 | struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id); | 439 | struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id); |
| 428 | void phy_device_free(struct phy_device *phydev); | 440 | void phy_device_free(struct phy_device *phydev); |
| 429 | 441 | ||
| 442 | int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask, | ||
| 443 | int (*run)(struct phy_device *)); | ||
| 444 | int phy_register_fixup_for_id(const char *bus_id, | ||
| 445 | int (*run)(struct phy_device *)); | ||
| 446 | int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask, | ||
| 447 | int (*run)(struct phy_device *)); | ||
| 448 | int phy_scan_fixups(struct phy_device *phydev); | ||
| 449 | |||
| 430 | extern struct bus_type mdio_bus_type; | 450 | extern struct bus_type mdio_bus_type; |
| 431 | #endif /* __PHY_H */ | 451 | #endif /* __PHY_H */ |
diff --git a/include/linux/xfrm.h b/include/linux/xfrm.h index 0c82c80b277f..2ca6bae88721 100644 --- a/include/linux/xfrm.h +++ b/include/linux/xfrm.h | |||
| @@ -97,10 +97,10 @@ struct xfrm_algo { | |||
| 97 | }; | 97 | }; |
| 98 | 98 | ||
| 99 | struct xfrm_algo_aead { | 99 | struct xfrm_algo_aead { |
| 100 | char alg_name[64]; | 100 | char alg_name[64]; |
| 101 | int alg_key_len; /* in bits */ | 101 | unsigned int alg_key_len; /* in bits */ |
| 102 | int alg_icv_len; /* in bits */ | 102 | unsigned int alg_icv_len; /* in bits */ |
| 103 | char alg_key[0]; | 103 | char alg_key[0]; |
| 104 | }; | 104 | }; |
| 105 | 105 | ||
| 106 | struct xfrm_stats { | 106 | struct xfrm_stats { |
diff --git a/include/mtd/Kbuild b/include/mtd/Kbuild index 4d46b3bdebd8..8eb018f96002 100644 --- a/include/mtd/Kbuild +++ b/include/mtd/Kbuild | |||
| @@ -3,5 +3,4 @@ header-y += jffs2-user.h | |||
| 3 | header-y += mtd-abi.h | 3 | header-y += mtd-abi.h |
| 4 | header-y += mtd-user.h | 4 | header-y += mtd-user.h |
| 5 | header-y += nftl-user.h | 5 | header-y += nftl-user.h |
| 6 | header-y += ubi-header.h | ||
| 7 | header-y += ubi-user.h | 6 | header-y += ubi-user.h |
diff --git a/kernel/sched.c b/kernel/sched.c index 0014b03adaca..09ca69b2c17d 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
| @@ -8128,7 +8128,7 @@ void __init sched_init(void) | |||
| 8128 | * we use alloc_bootmem(). | 8128 | * we use alloc_bootmem(). |
| 8129 | */ | 8129 | */ |
| 8130 | if (alloc_size) { | 8130 | if (alloc_size) { |
| 8131 | ptr = (unsigned long)alloc_bootmem_low(alloc_size); | 8131 | ptr = (unsigned long)alloc_bootmem(alloc_size); |
| 8132 | 8132 | ||
| 8133 | #ifdef CONFIG_FAIR_GROUP_SCHED | 8133 | #ifdef CONFIG_FAIR_GROUP_SCHED |
| 8134 | init_task_group.se = (struct sched_entity **)ptr; | 8134 | init_task_group.se = (struct sched_entity **)ptr; |
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 623ef24c2381..754cc0027f2a 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug | |||
| @@ -25,6 +25,17 @@ config ENABLE_MUST_CHECK | |||
| 25 | suppress the "warning: ignoring return value of 'foo', declared with | 25 | suppress the "warning: ignoring return value of 'foo', declared with |
| 26 | attribute warn_unused_result" messages. | 26 | attribute warn_unused_result" messages. |
| 27 | 27 | ||
| 28 | config FRAME_WARN | ||
| 29 | int "Warn for stack frames larger than (needs gcc 4.4)" | ||
| 30 | range 0 8192 | ||
| 31 | default 1024 if !64BIT | ||
| 32 | default 2048 if 64BIT | ||
| 33 | help | ||
| 34 | Tell gcc to warn at build time for stack frames larger than this. | ||
| 35 | Setting this too low will cause a lot of warnings. | ||
| 36 | Setting it to 0 disables the warning. | ||
| 37 | Requires gcc 4.4 | ||
| 38 | |||
| 28 | config MAGIC_SYSRQ | 39 | config MAGIC_SYSRQ |
| 29 | bool "Magic SysRq key" | 40 | bool "Magic SysRq key" |
| 30 | depends on !UML | 41 | depends on !UML |
diff --git a/net/can/raw.c b/net/can/raw.c index ead50c7c0d40..201cbfc6b9ec 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
| @@ -573,7 +573,8 @@ static int raw_getsockopt(struct socket *sock, int level, int optname, | |||
| 573 | int fsize = ro->count * sizeof(struct can_filter); | 573 | int fsize = ro->count * sizeof(struct can_filter); |
| 574 | if (len > fsize) | 574 | if (len > fsize) |
| 575 | len = fsize; | 575 | len = fsize; |
| 576 | err = copy_to_user(optval, ro->filter, len); | 576 | if (copy_to_user(optval, ro->filter, len)) |
| 577 | err = -EFAULT; | ||
| 577 | } else | 578 | } else |
| 578 | len = 0; | 579 | len = 0; |
| 579 | release_sock(sk); | 580 | release_sock(sk); |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index a29b43d0b450..0133b5ebd545 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
| @@ -323,6 +323,11 @@ static int ethtool_get_eeprom(struct net_device *dev, void __user *useraddr) | |||
| 323 | bytes_remaining -= eeprom.len; | 323 | bytes_remaining -= eeprom.len; |
| 324 | } | 324 | } |
| 325 | 325 | ||
| 326 | eeprom.len = userbuf - (useraddr + sizeof(eeprom)); | ||
| 327 | eeprom.offset -= eeprom.len; | ||
| 328 | if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) | ||
| 329 | ret = -EFAULT; | ||
| 330 | |||
| 326 | kfree(data); | 331 | kfree(data); |
| 327 | return ret; | 332 | return ret; |
| 328 | } | 333 | } |
diff --git a/net/dccp/probe.c b/net/dccp/probe.c index 6e1df62bd7c9..0bcdc9250279 100644 --- a/net/dccp/probe.c +++ b/net/dccp/probe.c | |||
| @@ -140,7 +140,7 @@ static ssize_t dccpprobe_read(struct file *file, char __user *buf, | |||
| 140 | goto out_free; | 140 | goto out_free; |
| 141 | 141 | ||
| 142 | cnt = kfifo_get(dccpw.fifo, tbuf, len); | 142 | cnt = kfifo_get(dccpw.fifo, tbuf, len); |
| 143 | error = copy_to_user(buf, tbuf, cnt); | 143 | error = copy_to_user(buf, tbuf, cnt) ? -EFAULT : 0; |
| 144 | 144 | ||
| 145 | out_free: | 145 | out_free: |
| 146 | vfree(tbuf); | 146 | vfree(tbuf); |
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index 1c509592574a..5ff0ce6e9d39 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c | |||
| @@ -190,19 +190,18 @@ static ssize_t tcpprobe_read(struct file *file, char __user *buf, | |||
| 190 | 190 | ||
| 191 | width = tcpprobe_sprint(tbuf, sizeof(tbuf)); | 191 | width = tcpprobe_sprint(tbuf, sizeof(tbuf)); |
| 192 | 192 | ||
| 193 | if (width < len) | 193 | if (cnt + width < len) |
| 194 | tcp_probe.tail = (tcp_probe.tail + 1) % bufsize; | 194 | tcp_probe.tail = (tcp_probe.tail + 1) % bufsize; |
| 195 | 195 | ||
| 196 | spin_unlock_bh(&tcp_probe.lock); | 196 | spin_unlock_bh(&tcp_probe.lock); |
| 197 | 197 | ||
| 198 | /* if record greater than space available | 198 | /* if record greater than space available |
| 199 | return partial buffer (so far) */ | 199 | return partial buffer (so far) */ |
| 200 | if (width >= len) | 200 | if (cnt + width >= len) |
| 201 | break; | 201 | break; |
| 202 | 202 | ||
| 203 | error = copy_to_user(buf + cnt, tbuf, width); | 203 | if (copy_to_user(buf + cnt, tbuf, width)) |
| 204 | if (error) | 204 | return -EFAULT; |
| 205 | break; | ||
| 206 | cnt += width; | 205 | cnt += width; |
| 207 | } | 206 | } |
| 208 | 207 | ||
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index 42814a2ec9d7..b2c9becc02e8 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
| @@ -167,7 +167,7 @@ config IPV6_SIT | |||
| 167 | Tunneling means encapsulating data of one protocol type within | 167 | Tunneling means encapsulating data of one protocol type within |
| 168 | another protocol and sending it over a channel that understands the | 168 | another protocol and sending it over a channel that understands the |
| 169 | encapsulating protocol. This driver implements encapsulation of IPv6 | 169 | encapsulating protocol. This driver implements encapsulation of IPv6 |
| 170 | into IPv4 packets. This is useful if you want to connect two IPv6 | 170 | into IPv4 packets. This is useful if you want to connect to IPv6 |
| 171 | networks over an IPv4-only path. | 171 | networks over an IPv4-only path. |
| 172 | 172 | ||
| 173 | Saying M here will produce a module called sit.ko. If unsure, say Y. | 173 | Saying M here will produce a module called sit.ko. If unsure, say Y. |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 6193b124cbc7..396f0ea11090 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
| @@ -971,6 +971,19 @@ static int do_rawv6_setsockopt(struct sock *sk, int level, int optname, | |||
| 971 | 971 | ||
| 972 | switch (optname) { | 972 | switch (optname) { |
| 973 | case IPV6_CHECKSUM: | 973 | case IPV6_CHECKSUM: |
| 974 | if (inet_sk(sk)->num == IPPROTO_ICMPV6 && | ||
| 975 | level == IPPROTO_IPV6) { | ||
| 976 | /* | ||
| 977 | * RFC3542 tells that IPV6_CHECKSUM socket | ||
| 978 | * option in the IPPROTO_IPV6 level is not | ||
| 979 | * allowed on ICMPv6 sockets. | ||
| 980 | * If you want to set it, use IPPROTO_RAW | ||
| 981 | * level IPV6_CHECKSUM socket option | ||
| 982 | * (Linux extension). | ||
| 983 | */ | ||
| 984 | return -EINVAL; | ||
| 985 | } | ||
| 986 | |||
| 974 | /* You may get strange result with a positive odd offset; | 987 | /* You may get strange result with a positive odd offset; |
| 975 | RFC2292bis agrees with me. */ | 988 | RFC2292bis agrees with me. */ |
| 976 | if (val > 0 && (val&1)) | 989 | if (val > 0 && (val&1)) |
| @@ -1046,6 +1059,11 @@ static int do_rawv6_getsockopt(struct sock *sk, int level, int optname, | |||
| 1046 | 1059 | ||
| 1047 | switch (optname) { | 1060 | switch (optname) { |
| 1048 | case IPV6_CHECKSUM: | 1061 | case IPV6_CHECKSUM: |
| 1062 | /* | ||
| 1063 | * We allow getsockopt() for IPPROTO_IPV6-level | ||
| 1064 | * IPV6_CHECKSUM socket option on ICMPv6 sockets | ||
| 1065 | * since RFC3542 is silent about it. | ||
| 1066 | */ | ||
| 1049 | if (rp->checksum == 0) | 1067 | if (rp->checksum == 0) |
| 1050 | val = -1; | 1068 | val = -1; |
| 1051 | else | 1069 | else |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 81a8e5297ad1..2403a31fe0f6 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
| @@ -2356,7 +2356,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
| 2356 | struct xfrm_selector sel; | 2356 | struct xfrm_selector sel; |
| 2357 | struct km_event c; | 2357 | struct km_event c; |
| 2358 | struct sadb_x_sec_ctx *sec_ctx; | 2358 | struct sadb_x_sec_ctx *sec_ctx; |
| 2359 | struct xfrm_sec_ctx *pol_ctx; | 2359 | struct xfrm_sec_ctx *pol_ctx = NULL; |
| 2360 | 2360 | ||
| 2361 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], | 2361 | if (!present_and_same_family(ext_hdrs[SADB_EXT_ADDRESS_SRC-1], |
| 2362 | ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || | 2362 | ext_hdrs[SADB_EXT_ADDRESS_DST-1]) || |
| @@ -2396,8 +2396,7 @@ static int pfkey_spddelete(struct sock *sk, struct sk_buff *skb, struct sadb_msg | |||
| 2396 | kfree(uctx); | 2396 | kfree(uctx); |
| 2397 | if (err) | 2397 | if (err) |
| 2398 | return err; | 2398 | return err; |
| 2399 | } else | 2399 | } |
| 2400 | pol_ctx = NULL; | ||
| 2401 | 2400 | ||
| 2402 | xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, | 2401 | xp = xfrm_policy_bysel_ctx(XFRM_POLICY_TYPE_MAIN, |
| 2403 | pol->sadb_x_policy_dir - 1, &sel, pol_ctx, | 2402 | pol->sadb_x_policy_dir - 1, &sel, pol_ctx, |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 05853159536a..230f9ca2ad6b 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -1756,8 +1756,8 @@ static int getsockopt(struct socket *sock, | |||
| 1756 | else if (len < sizeof(value)) { | 1756 | else if (len < sizeof(value)) { |
| 1757 | res = -EINVAL; | 1757 | res = -EINVAL; |
| 1758 | } | 1758 | } |
| 1759 | else if ((res = copy_to_user(ov, &value, sizeof(value)))) { | 1759 | else if (copy_to_user(ov, &value, sizeof(value))) { |
| 1760 | /* couldn't return value */ | 1760 | res = -EFAULT; |
| 1761 | } | 1761 | } |
| 1762 | else { | 1762 | else { |
| 1763 | res = put_user(sizeof(value), ol); | 1763 | res = put_user(sizeof(value), ol); |
diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 67fb4530a6ff..277cfe0b7100 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build | |||
| @@ -27,12 +27,12 @@ ccflags-y := | |||
| 27 | cppflags-y := | 27 | cppflags-y := |
| 28 | ldflags-y := | 28 | ldflags-y := |
| 29 | 29 | ||
| 30 | # Read .config if it exist, otherwise ignore | 30 | # Read auto.conf if it exists, otherwise ignore |
| 31 | -include include/config/auto.conf | 31 | -include include/config/auto.conf |
| 32 | 32 | ||
| 33 | include scripts/Kbuild.include | 33 | include scripts/Kbuild.include |
| 34 | 34 | ||
| 35 | # For backward compatibility check that these variables does not change | 35 | # For backward compatibility check that these variables do not change |
| 36 | save-cflags := $(CFLAGS) | 36 | save-cflags := $(CFLAGS) |
| 37 | 37 | ||
| 38 | # The filename Kbuild has precedence over Makefile | 38 | # The filename Kbuild has precedence over Makefile |
| @@ -55,7 +55,7 @@ hostprogs-y += $(host-progs) | |||
| 55 | endif | 55 | endif |
| 56 | endif | 56 | endif |
| 57 | 57 | ||
| 58 | # Do not include host rules unles needed | 58 | # Do not include host rules unless needed |
| 59 | ifneq ($(hostprogs-y)$(hostprogs-m),) | 59 | ifneq ($(hostprogs-y)$(hostprogs-m),) |
| 60 | include scripts/Makefile.host | 60 | include scripts/Makefile.host |
| 61 | endif | 61 | endif |
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean index 2c647107c9cc..6f89fbb56256 100644 --- a/scripts/Makefile.clean +++ b/scripts/Makefile.clean | |||
| @@ -37,7 +37,7 @@ subdir-ymn := $(sort $(subdir-ym) $(subdir-n) $(subdir-)) | |||
| 37 | 37 | ||
| 38 | subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn)) | 38 | subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn)) |
| 39 | 39 | ||
| 40 | # build a list of files to remove, usually releative to the current | 40 | # build a list of files to remove, usually relative to the current |
| 41 | # directory | 41 | # directory |
| 42 | 42 | ||
| 43 | __clean-files := $(extra-y) $(always) \ | 43 | __clean-files := $(extra-y) $(always) \ |
diff --git a/scripts/Makefile.host b/scripts/Makefile.host index 6943a7a5bb98..1ac414fd5030 100644 --- a/scripts/Makefile.host +++ b/scripts/Makefile.host | |||
| @@ -3,9 +3,9 @@ | |||
| 3 | # Binaries are used during the compilation of the kernel, for example | 3 | # Binaries are used during the compilation of the kernel, for example |
| 4 | # to preprocess a data file. | 4 | # to preprocess a data file. |
| 5 | # | 5 | # |
| 6 | # Both C and C++ is supported, but preferred language is C for such utilities. | 6 | # Both C and C++ are supported, but preferred language is C for such utilities. |
| 7 | # | 7 | # |
| 8 | # Samle syntax (see Documentation/kbuild/makefile.txt for reference) | 8 | # Sample syntax (see Documentation/kbuild/makefiles.txt for reference) |
| 9 | # hostprogs-y := bin2hex | 9 | # hostprogs-y := bin2hex |
| 10 | # Will compile bin2hex.c and create an executable named bin2hex | 10 | # Will compile bin2hex.c and create an executable named bin2hex |
| 11 | # | 11 | # |
| @@ -23,10 +23,10 @@ | |||
| 23 | # hostprogs-y := conf | 23 | # hostprogs-y := conf |
| 24 | # conf-objs := conf.o libkconfig.so | 24 | # conf-objs := conf.o libkconfig.so |
| 25 | # libkconfig-objs := expr.o type.o | 25 | # libkconfig-objs := expr.o type.o |
| 26 | # Will create a shared library named libkconfig.so that consist of | 26 | # Will create a shared library named libkconfig.so that consists of |
| 27 | # expr.o and type.o (they are both compiled as C code and the object file | 27 | # expr.o and type.o (they are both compiled as C code and the object files |
| 28 | # are made as position independent code). | 28 | # are made as position independent code). |
| 29 | # conf.c is compiled as a c program, and conf.o is linked together with | 29 | # conf.c is compiled as a C program, and conf.o is linked together with |
| 30 | # libkconfig.so as the executable conf. | 30 | # libkconfig.so as the executable conf. |
| 31 | # Note: Shared libraries consisting of C++ files are not supported | 31 | # Note: Shared libraries consisting of C++ files are not supported |
| 32 | 32 | ||
| @@ -61,7 +61,7 @@ host-cobjs := $(filter-out %.so,$(host-cobjs)) | |||
| 61 | host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs)))) | 61 | host-cshobjs := $(sort $(foreach m,$(host-cshlib),$($(m:.so=-objs)))) |
| 62 | 62 | ||
| 63 | # output directory for programs/.o files | 63 | # output directory for programs/.o files |
| 64 | # hostprogs-y := tools/build may have been specified. Retreive directory | 64 | # hostprogs-y := tools/build may have been specified. Retrieve directory |
| 65 | host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f)))) | 65 | host-objdirs := $(foreach f,$(__hostprogs), $(if $(dir $(f)),$(dir $(f)))) |
| 66 | # directory of .o files from prog-objs notation | 66 | # directory of .o files from prog-objs notation |
| 67 | host-objdirs += $(foreach f,$(host-cmulti), \ | 67 | host-objdirs += $(foreach f,$(host-cmulti), \ |
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 2d20640854b7..24b3c8fe6bca 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost | |||
| @@ -42,6 +42,13 @@ _modpost: __modpost | |||
| 42 | 42 | ||
| 43 | include include/config/auto.conf | 43 | include include/config/auto.conf |
| 44 | include scripts/Kbuild.include | 44 | include scripts/Kbuild.include |
| 45 | |||
| 46 | ifneq ($(KBUILD_EXTMOD),) | ||
| 47 | # Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS | ||
| 48 | include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \ | ||
| 49 | $(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile) | ||
| 50 | endif | ||
| 51 | |||
| 45 | include scripts/Makefile.lib | 52 | include scripts/Makefile.lib |
| 46 | 53 | ||
| 47 | kernelsymfile := $(objtree)/Module.symvers | 54 | kernelsymfile := $(objtree)/Module.symvers |
| @@ -69,6 +76,7 @@ modpost = scripts/mod/modpost \ | |||
| 69 | $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \ | 76 | $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \ |
| 70 | $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \ | 77 | $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \ |
| 71 | $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \ | 78 | $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \ |
| 79 | $(if $(iKBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(EXTRA_SYMBOLS))) \ | ||
| 72 | $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ | 80 | $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ |
| 73 | $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \ | 81 | $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \ |
| 74 | $(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \ | 82 | $(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \ |
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 110cf243fa4e..f8b42ab0724b 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
| @@ -1552,6 +1552,10 @@ static void read_symbols(char *modname) | |||
| 1552 | } | 1552 | } |
| 1553 | 1553 | ||
| 1554 | license = get_modinfo(info.modinfo, info.modinfo_len, "license"); | 1554 | license = get_modinfo(info.modinfo, info.modinfo_len, "license"); |
| 1555 | if (!license && !is_vmlinux(modname)) | ||
| 1556 | fatal("modpost: missing MODULE_LICENSE() in %s\n" | ||
| 1557 | "see include/linux/module.h for " | ||
| 1558 | "more information\n", modname); | ||
| 1555 | while (license) { | 1559 | while (license) { |
| 1556 | if (license_is_gpl_compatible(license)) | 1560 | if (license_is_gpl_compatible(license)) |
| 1557 | mod->gpl_compatible = 1; | 1561 | mod->gpl_compatible = 1; |
| @@ -2015,6 +2019,11 @@ static void write_markers(const char *fname) | |||
| 2015 | write_if_changed(&buf, fname); | 2019 | write_if_changed(&buf, fname); |
| 2016 | } | 2020 | } |
| 2017 | 2021 | ||
| 2022 | struct ext_sym_list { | ||
| 2023 | struct ext_sym_list *next; | ||
| 2024 | const char *file; | ||
| 2025 | }; | ||
| 2026 | |||
| 2018 | int main(int argc, char **argv) | 2027 | int main(int argc, char **argv) |
| 2019 | { | 2028 | { |
| 2020 | struct module *mod; | 2029 | struct module *mod; |
| @@ -2025,8 +2034,10 @@ int main(int argc, char **argv) | |||
| 2025 | char *markers_write = NULL; | 2034 | char *markers_write = NULL; |
| 2026 | int opt; | 2035 | int opt; |
| 2027 | int err; | 2036 | int err; |
| 2037 | struct ext_sym_list *extsym_iter; | ||
| 2038 | struct ext_sym_list *extsym_start = NULL; | ||
| 2028 | 2039 | ||
| 2029 | while ((opt = getopt(argc, argv, "i:I:cmsSo:awM:K:")) != -1) { | 2040 | while ((opt = getopt(argc, argv, "i:I:e:cmsSo:awM:K:")) != -1) { |
| 2030 | switch (opt) { | 2041 | switch (opt) { |
| 2031 | case 'i': | 2042 | case 'i': |
| 2032 | kernel_read = optarg; | 2043 | kernel_read = optarg; |
| @@ -2038,6 +2049,14 @@ int main(int argc, char **argv) | |||
| 2038 | case 'c': | 2049 | case 'c': |
| 2039 | cross_build = 1; | 2050 | cross_build = 1; |
| 2040 | break; | 2051 | break; |
| 2052 | case 'e': | ||
| 2053 | external_module = 1; | ||
| 2054 | extsym_iter = | ||
| 2055 | NOFAIL(malloc(sizeof(*extsym_iter))); | ||
| 2056 | extsym_iter->next = extsym_start; | ||
| 2057 | extsym_iter->file = optarg; | ||
| 2058 | extsym_start = extsym_iter; | ||
| 2059 | break; | ||
| 2041 | case 'm': | 2060 | case 'm': |
| 2042 | modversions = 1; | 2061 | modversions = 1; |
| 2043 | break; | 2062 | break; |
| @@ -2071,6 +2090,12 @@ int main(int argc, char **argv) | |||
| 2071 | read_dump(kernel_read, 1); | 2090 | read_dump(kernel_read, 1); |
| 2072 | if (module_read) | 2091 | if (module_read) |
| 2073 | read_dump(module_read, 0); | 2092 | read_dump(module_read, 0); |
| 2093 | while (extsym_start) { | ||
| 2094 | read_dump(extsym_start->file, 0); | ||
| 2095 | extsym_iter = extsym_start->next; | ||
| 2096 | free(extsym_start); | ||
| 2097 | extsym_start = extsym_iter; | ||
| 2098 | } | ||
| 2074 | 2099 | ||
| 2075 | while (optind < argc) | 2100 | while (optind < argc) |
| 2076 | read_symbols(argv[optind++]); | 2101 | read_symbols(argv[optind++]); |
