summaryrefslogtreecommitdiff
path: root/drivers/staging/unisys/visornic
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/unisys/visornic')
-rw-r--r--drivers/staging/unisys/visornic/visornic_main.c37
1 files changed, 37 insertions, 0 deletions
diff --git a/drivers/staging/unisys/visornic/visornic_main.c b/drivers/staging/unisys/visornic/visornic_main.c
index b961d7e1ae7b..89de87fa9e4d 100644
--- a/drivers/staging/unisys/visornic/visornic_main.c
+++ b/drivers/staging/unisys/visornic/visornic_main.c
@@ -141,6 +141,43 @@ struct visornic_devdata {
struct uiscmdrsp cmdrsp[SIZEOF_CMDRSP];
};
+/* Returns next non-zero index on success or 0 on failure (i.e. out of room). */
+static inline u16
+add_physinfo_entries(u64 inp_pfn, u16 inp_off, u32 inp_len, u16 index,
+ u16 max_pi_arr_entries, struct phys_info pi_arr[])
+{
+ u32 len;
+ u16 i, firstlen;
+
+ firstlen = PI_PAGE_SIZE - inp_off;
+ if (inp_len <= firstlen) {
+ /* The input entry spans only one page - add as is. */
+ if (index >= max_pi_arr_entries)
+ return 0;
+ pi_arr[index].pi_pfn = inp_pfn;
+ pi_arr[index].pi_off = (u16)inp_off;
+ pi_arr[index].pi_len = (u16)inp_len;
+ return index + 1;
+ }
+
+ /* This entry spans multiple pages. */
+ for (len = inp_len, i = 0; len;
+ len -= pi_arr[index + i].pi_len, i++) {
+ if (index + i >= max_pi_arr_entries)
+ return 0;
+ pi_arr[index + i].pi_pfn = inp_pfn + i;
+ if (i == 0) {
+ pi_arr[index].pi_off = inp_off;
+ pi_arr[index].pi_len = firstlen;
+ } else {
+ pi_arr[index + i].pi_off = 0;
+ pi_arr[index + i].pi_len =
+ (u16)MINNUM(len, (u32)PI_PAGE_SIZE);
+ }
+ }
+ return index + i;
+}
+
/*
* visor_copy_fragsinfo_from_skb(
* @skb_in: skbuff that we are pulling the frags from