Re: [PATCH V8 1/6] LIBIO: Introduce a generic PIO mapping method

zhichang.yuan
2017-04-05T12:19:32Z

Hi,

Thanks for your report!

I am sorry for that!

This issue was caused by missing the '#include <linux/logic_pio.h>' in
logic_pio.c for some architectures where the 'asm-generic/io.h' wasn't been
included.

Will be fixed in the next V9.

Apologized for this!

-Zhichang

On 04/01/2017 01:58 PM, kbuild test robot wrote:
> Hi zhichang.yuan,
>
> [auto build test ERROR on linus/master]
> [also build test ERROR on v4.11-rc4 next-20170331]
> [if your patch is applied to the wrong git tree, please drop us a note to help improve the system]
>
> url: https://github.com/0day-ci/linux/commits/zhichang-yuan/LIBIO-Introduce-a-generic-PIO-mapping-method/20170401-104801
> config: alpha-allyesconfig (attached as .config)
> compiler: alpha-linux-gnu-gcc (Debian 6.1.1-9) 6.1.1 20160705
> reproduce:
> wget https://raw.githubusercontent.com/01org/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
> chmod +x ~/bin/make.cross
> # save the attached .config to linux build tree
> make.cross ARCH=alpha
>
> All error/warnings (new ones prefixed by >>):
>
>>> lib/logic_pio.c:32:50: error: 'PIO_MAX_SECT' undeclared here (not in a function)
> static struct logic_pio_root logic_pio_root_list[PIO_MAX_SECT] = {
> ^~~~~~~~~~~~
>>> lib/logic_pio.c:39:3: error: 'PIO_CPU_MMIO' undeclared here (not in a function)
> [PIO_CPU_MMIO ... PIO_INDIRECT - 1] = {
> ^~~~~~~~~~~~
>>> lib/logic_pio.c:39:20: error: 'PIO_INDIRECT' undeclared here (not in a function)
> [PIO_CPU_MMIO ... PIO_INDIRECT - 1] = {
> ^~~~~~~~~~~~
>>> lib/logic_pio.c:39:3: error: array index in initializer not of integer type
> [PIO_CPU_MMIO ... PIO_INDIRECT - 1] = {
> ^~~~~~~~~~~~
> lib/logic_pio.c:39:3: note: (near initialization for 'logic_pio_root_list')
>>> lib/logic_pio.c:40:3: error: field name not in record or union initializer
> .sec_head = LIST_HEAD_INIT(logic_pio_root_list[PIO_CPU_MMIO].sec_head),
> ^
> lib/logic_pio.c:40:3: note: (near initialization for 'logic_pio_root_list')
> lib/logic_pio.c:41:3: error: field name not in record or union initializer
> .sec_min = PIO_SECT_MIN(PIO_CPU_MMIO),
> ^
> lib/logic_pio.c:41:3: note: (near initialization for 'logic_pio_root_list')
>>> lib/logic_pio.c:41:14: error: implicit declaration of function 'PIO_SECT_MIN' [-Werror=implicit-function-declaration]
> .sec_min = PIO_SECT_MIN(PIO_CPU_MMIO),
> ^~~~~~~~~~~~
> lib/logic_pio.c:42:3: error: field name not in record or union initializer
> .sec_max = PIO_SECT_MAX(PIO_INDIRECT - 1),
> ^
> lib/logic_pio.c:42:3: note: (near initialization for 'logic_pio_root_list')
>>> lib/logic_pio.c:42:14: error: implicit declaration of function 'PIO_SECT_MAX' [-Werror=implicit-function-declaration]
> .sec_max = PIO_SECT_MAX(PIO_INDIRECT - 1),
> ^~~~~~~~~~~~
> lib/logic_pio.c:46:3: error: array index in initializer not of integer type
> [PIO_INDIRECT] = {
> ^~~~~~~~~~~~
> lib/logic_pio.c:46:3: note: (near initialization for 'logic_pio_root_list')
> lib/logic_pio.c:47:3: error: field name not in record or union initializer
> .sec_head = LIST_HEAD_INIT(logic_pio_root_list[PIO_INDIRECT].sec_head),
> ^
> lib/logic_pio.c:47:3: note: (near initialization for 'logic_pio_root_list')
> lib/logic_pio.c:48:3: error: field name not in record or union initializer
> .sec_min = PIO_SECT_MIN(PIO_INDIRECT),
> ^
> lib/logic_pio.c:48:3: note: (near initialization for 'logic_pio_root_list')
> lib/logic_pio.c:49:3: error: field name not in record or union initializer
> .sec_max = PIO_SECT_MAX(PIO_INDIRECT),
> ^
> lib/logic_pio.c:49:3: note: (near initialization for 'logic_pio_root_list')
> In file included from include/linux/list.h:8:0,
> from include/linux/kobject.h:20,
> from include/linux/of.h:21,
> from lib/logic_pio.c:18:
> lib/logic_pio.c: In function 'logic_pio_find_range_byaddr':
>>> include/linux/rculist.h:351:49: error: dereferencing pointer to incomplete type 'struct logic_pio_hwaddr'
> for (pos = list_entry_rcu((head)->next, typeof(*pos), member); \
>
> include/linux/kernel.h:852:18: note: in definition of macro 'container_of'
> const typeof( ((type *)0)->member ) *__mptr = (ptr); \
> ^~~~
>>> include/linux/rculist.h:351:13: note: in expansion of macro 'list_entry_rcu'
> for (pos = list_entry_rcu((head)->next, typeof(*pos), member); \
> ^~~~~~~~~~~~~~
>>> lib/logic_pio.c:77:2: note: in expansion of macro 'list_for_each_entry_rcu'
> list_for_each_entry_rcu(range, &io_range_list, list) {
> ^~~~~~~~~~~~~~~~~~~~~~~
> include/linux/kernel.h:852:48: error: initialization from incompatible pointer type [-Werror=incompatible-pointer-types]
> const typeof( ((type *)0)->member ) *__mptr = (ptr); \
> ^
>>> include/linux/rculist.h:277:2: note: in expansion of macro 'container_of'
> container_of(lockless_dereference(ptr), type, member)
> ^~~~~~~~~~~~
>>> include/linux/rculist.h:351:13: note: in expansion of macro 'list_entry_rcu'
> for (pos = list_entry_rcu((head)->next, typeof(*pos), member); \
> ^~~~~~~~~~~~~~
>>> lib/logic_pio.c:77:2: note: in expansion of macro 'list_for_each_entry_rcu'
> list_for_each_entry_rcu(range, &io_range_list, list) {
> ^~~~~~~~~~~~~~~~~~~~~~~
>>> include/linux/kernel.h:852:48: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
> const typeof( ((type *)0)->member ) *__mptr = (ptr); \
> ^
>>> include/linux/rculist.h:277:2: note: in expansion of macro 'container_of'
> container_of(lockless_dereference(ptr), type, member)
> ^~~~~~~~~~~~
> include/linux/rculist.h:353:9: note: in expansion of macro 'list_entry_rcu'
> pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
> ^~~~~~~~~~~~~~
>>> lib/logic_pio.c:77:2: note: in expansion of macro 'list_for_each_entry_rcu'
> list_for_each_entry_rcu(range, &io_range_list, list) {
> ^~~~~~~~~~~~~~~~~~~~~~~
> lib/logic_pio.c: In function 'logic_pio_alloc_range':
>>> lib/logic_pio.c:109:19: error: dereferencing pointer to incomplete type 'struct logic_pio_root'
> idle_start = root->sec_min;
> ^~
> In file included from include/linux/list.h:8:0,
> from include/linux/kobject.h:20,
> from include/linux/of.h:21,
> from lib/logic_pio.c:18:
>>> include/linux/rculist.h:351:49: error: dereferencing pointer to incomplete type 'struct logic_pio_sect'
> for (pos = list_entry_rcu((head)->next, typeof(*pos), member); \
>
> include/linux/kernel.h:852:18: note: in definition of macro 'container_of'
> const typeof( ((type *)0)->member ) *__mptr = (ptr); \
> ^~~~
>>> include/linux/rculist.h:351:13: note: in expansion of macro 'list_entry_rcu'
> for (pos = list_entry_rcu((head)->next, typeof(*pos), member); \
> ^~~~~~~~~~~~~~
> lib/logic_pio.c:111:2: note: in expansion of macro 'list_for_each_entry_rcu'
> list_for_each_entry_rcu(entry, &root->sec_head, list) {
> ^~~~~~~~~~~~~~~~~~~~~~~
>>> include/linux/kernel.h:852:48: warning: initialization makes pointer from integer without a cast [-Wint-conversion]
> const typeof( ((type *)0)->member ) *__mptr = (ptr); \
> ^
>
> vim +/PIO_MAX_SECT +32 lib/logic_pio.c
>
> 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, see <http://www.gnu.org/licenses/>.
> 16 */
> 17
> > 18 #include <linux/of.h>
> 19 #include <linux/io.h>
> 20 #include <linux/mm.h>
> 21 #include <linux/rculist.h>
> 22 #include <linux/sizes.h>
> 23 #include <linux/slab.h>
> 24
> 25 /* The unique hardware address list. */
> 26 static LIST_HEAD(io_range_list);
> 27 static DEFINE_MUTEX(io_range_mutex);
> 28
> 29 /*
> 30 * These are the lists for PIO. The highest PIO_SECT_BITS of PIO is the index.
> 31 */
> > 32 static struct logic_pio_root logic_pio_root_list[PIO_MAX_SECT] = {
> 33 #ifdef CONFIG_INDIRECT_PIO
> 34 /*
> 35 * At this moment, assign all the other logic PIO space to MMIO.
> 36 * If more elements added, please adjust the ending index and .sec_max;
> 37 * Please keep MMIO element started from index ZERO.
> 38 */
> > 39 [PIO_CPU_MMIO ... PIO_INDIRECT - 1] = {
> > 40 .sec_head = LIST_HEAD_INIT(logic_pio_root_list[PIO_CPU_MMIO].sec_head),
> > 41 .sec_min = PIO_SECT_MIN(PIO_CPU_MMIO),
> > 42 .sec_max = PIO_SECT_MAX(PIO_INDIRECT - 1),
> 43 },
> 44
> 45 /* The last element */
> 46 [PIO_INDIRECT] = {
> 47 .sec_head = LIST_HEAD_INIT(logic_pio_root_list[PIO_INDIRECT].sec_head),
> 48 .sec_min = PIO_SECT_MIN(PIO_INDIRECT),
> 49 .sec_max = PIO_SECT_MAX(PIO_INDIRECT),
> 50 },
> 51 #else
> 52 [PIO_CPU_MMIO] = {
> 53 .sec_head = LIST_HEAD_INIT(logic_pio_root_list[PIO_CPU_MMIO].sec_head),
> 54 .sec_min = PIO_SECT_MIN(PIO_CPU_MMIO),
> 55 .sec_max = PIO_SECT_MAX(PIO_CPU_MMIO),
> 56 },
> 57
> 58 #endif
> 59 };
> 60
> 61 /*
> 62 * Search a io_range registered which match the fwnode and addr.
> 63 *
> 64 * @fwnode: the host fwnode which must be valid;
> 65 * @start: the start hardware address of this search;
> 66 * @end: the end hardware address of this search. can be equal to @start;
> 67 *
> 68 * return NULL when there is no matched node; IS_ERR() means ERROR;
> 69 * valid virtual address represent a matched node was found.
> 70 */
> 71 static struct logic_pio_hwaddr *
> 72 logic_pio_find_range_byaddr(struct fwnode_handle *fwnode,
> 73 resource_size_t start, resource_size_t end)
> 74 {
> 75 struct logic_pio_hwaddr *range;
> 76
> > 77 list_for_each_entry_rcu(range, &io_range_list, list) {
> 78 if (!range->pio_peer) {
> 79 pr_warn("Invalid cpu addr node(%pa) in list!\n",
> 80 &range->hw_start);
> 81 continue;
> 82 }
> 83 if (range->fwnode != fwnode)
> 84 continue;
> 85 /* without any overlap with current range */
> 86 if (start >= range->hw_start + range->size ||
> 87 end < range->hw_start)
> 88 continue;
> 89 /* overlap is not supported now. */
> 90 if (start < range->hw_start ||
> 91 end >= range->hw_start + range->size)
> 92 return ERR_PTR(-EBUSY);
> 93 /* had been registered. */
> 94 return range;
> 95 }
> 96
> 97 return NULL;
> 98 }
> 99
> 100
> 101 static int logic_pio_alloc_range(struct logic_pio_root *root,
> 102 resource_size_t size, unsigned long align,
> 103 struct list_head **prev, resource_size_t *pio_alloc)
> 104 {
> 105 struct logic_pio_sect *entry;
> 106 resource_size_t tmp_start;
> 107 resource_size_t idle_start, idle_end;
> 108
> > 109 idle_start = root->sec_min;
> 110 *prev = &root->sec_head;
> 111 list_for_each_entry_rcu(entry, &root->sec_head, list) {
> 112 if (!entry->hwpeer ||
> 113 idle_start > entry->io_start) {
> 114 WARN(1, "skip an invalid io range during traversal!\n");
> 115 goto nextentry;
> 116 }
> 117 /* set the end edge. */
> 118 if (idle_start == entry->io_start) {
> 119 struct logic_pio_sect *next;
> 120
> 121 idle_start = entry->io_start + entry->hwpeer->size;
> > 122 next = list_next_or_null_rcu(&root->sec_head,
> > 123 &entry->list, struct logic_pio_sect, list);
> 124 if (next) {
> 125 entry = next;
> 126 } else {
> 127 *prev = &entry->list;
> 128 break;
> 129 }
> 130 }
> 131 idle_end = entry->io_start - 1;
> 132
> 133 /* contiguous range... */
> 134 if (idle_start > idle_end)
> 135 goto nextentry;
> 136
> 137 tmp_start = idle_start;
> 138 idle_start = ALIGN(idle_start, align);
> 139 if (idle_start >= tmp_start &&
> 140 idle_start + size <= idle_end) {
> 141 *prev = &entry->list;
> 142 *pio_alloc = idle_start;
> 143 return 0;
> 144 }
> 145
> 146 nextentry:
> 147 idle_start = entry->io_start + entry->hwpeer->size;
> 148 *prev = &entry->list;
> 149 }
> 150 /* check the last free gap... */
> 151 idle_end = root->sec_max;
> 152
> 153 tmp_start = idle_start;
> 154 idle_start = ALIGN(idle_start, align);
> 155 if (idle_start >= tmp_start &&
> 156 idle_start + size <= idle_end) {
> 157 *pio_alloc = idle_start;
> 158 return 0;
> 159 }
> 160
> 161 return -EBUSY;
> 162 }
> 163
> 164 /*
> 165 * register a io range node in the io range list.
> 166 *
> 167 * @newrange: pointer to the io range to be registered.
> 168 *
> 169 * return 'newrange' when success, ERR_VALUE() is for failures.
> 170 * specially, return a valid pointer which is not equal to 'newrange' when
> 171 * the io range had been registered before.
> 172 */
> 173 struct logic_pio_hwaddr
> 174 *logic_pio_register_range(struct logic_pio_hwaddr *newrange,
> 175 unsigned long align)
> 176 {
> 177 struct logic_pio_hwaddr *range;
> 178 struct logic_pio_sect *newsect;
> 179 resource_size_t pio_alloc;
> 180 struct list_head *prev, *hwprev;
> 181 unsigned long sect_id;
> 182 int err;
> 183
> 184 if (!newrange || !newrange->fwnode || !newrange->size)
> 185 return ERR_PTR(-EINVAL);
> 186
> 187 sect_id = newrange->flags;
> 188 if (sect_id >= PIO_MAX_SECT)
> 189 return ERR_PTR(-EINVAL);
> 190
> 191 mutex_lock(&io_range_mutex);
> 192 range = logic_pio_find_range_byaddr(newrange->fwnode,
> 193 newrange->hw_start,
> 194 newrange->hw_start + newrange->size - 1);
> 195 if (range) {
> 196 if (!IS_ERR(range))
> 197 pr_info("the request IO range had been registered!\n");
> 198 else
> 199 pr_err("registering IO[%pa - sz%pa) got failed!\n",
> 200 &newrange->hw_start, &newrange->size);
> 201 mutex_unlock(&io_range_mutex);
> 202 return range;
> 203 }
> 204
> 205 err = logic_pio_alloc_range(&logic_pio_root_list[sect_id],
> 206 newrange->size, align, &prev, &pio_alloc);
> 207 if (err) {
> 208 pr_err("can't find free %pa logical IO range!\n",
> 209 &newrange->size);
> 210 goto exitproc;
> 211 }
> 212
> 213 if (prev == &logic_pio_root_list[sect_id].sec_head) {
> 214 hwprev = &io_range_list;
> 215 } else {
> > 216 newsect = to_pio_sect(prev);
> > 217 hwprev = &newsect->hwpeer->list;
> 218 }
> 219
> 220 newsect = kzalloc(sizeof(*newsect), GFP_KERNEL);
>
> ---
> 0-DAY kernel test infrastructure Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all Intel Corporation
>